Skip to Content
Component ExamplesPopovers

Overview

The Popover API is a browser-native mechanism for creating light-dismiss overlays — popovers that close when the user clicks outside, presses Escape, or opens another popover. It handles top-layer rendering, light dismiss, and aria-expanded toggling automatically. However, the Popover API does not add a semantic role — you must add role="dialog", role="tooltip", or another appropriate role yourself. The API reached Baseline Widely Available in April 2025, meaning it is supported across all major browsers.

WCAG Criteria:

Key requirements:

  • Use the popover attribute on the target element and popovertarget on the invoking button
  • Add role="dialog" or role="tooltip" yourself — the Popover API does not provide semantic roles
  • Provide an accessible name via aria-label or aria-labelledby
  • The browser automatically handles Escape to dismiss, light dismiss (click outside), and aria-expanded on the trigger button
  • Use popover="auto" for light-dismiss behavior (closes when another auto popover opens or when clicking outside)
  • Use popover="manual" when you need explicit open/close control without light dismiss

Basic Popover

Custom Toggle Div vs. Native Popover API

Inaccessible
<!-- Custom div popover — no Escape, no light dismiss, no ARIA --> <button onclick="togglePopover()">More Info</button> <div id="popover" style="display:none"> <p>This feature allows you to export your data in multiple formats including CSV, JSON, and PDF.</p> <a href="#">Learn more about exports</a> </div>
Live Preview
Accessible
<!-- Native Popover API — Escape, light dismiss, aria-expanded --> <button popovertarget="pop">More Info</button> <div popover="auto" id="pop" role="dialog" aria-label="Additional information" > <p>This feature allows you to export your data in multiple formats including CSV, JSON, and PDF.</p> <a href="#">Learn more about exports</a> </div>
Live Preview

What’s wrong with the custom div popover?

  • No role — screen readers treat it as generic content, not a dialog or overlay
  • No aria-label or aria-labelledby — screen readers cannot identify the purpose of the overlay
  • No Escape key handling — keyboard users must find and click a close button or tab away
  • No light dismiss — clicking outside the popover does nothing; it stays open
  • No aria-expanded on the trigger — screen readers cannot tell whether the popover is open or closed
  • Manual display toggling is fragile and does not handle stacking context or top-layer rendering

What the native Popover API provides:

  • Escape key closes the popover automatically
  • Light dismiss — clicking outside closes the popover
  • aria-expanded is automatically toggled on the trigger button (the popovertarget button)
  • Top-layer rendering — the popover is promoted to the browser’s top layer, avoiding z-index conflicts
  • Auto stacking — when a new popover="auto" opens, the previous one closes
  • The API does not add a semantic role — you must add role="dialog", role="tooltip", or another appropriate role yourself

What the screen reader announces:

VersionAnnouncement
Custom div”More Info, button” (no expanded state, popover content has no role)
Popover API”More Info, expanded, button” then “Additional information, dialog” (role and name announced)

popover="auto" vs popover="manual":

Behaviorautomanual
Light dismiss (click outside)YesNo
Escape closesYesNo
Closes when another auto popover opensYesNo
aria-expanded toggled on triggerYesYes
Use caseMenus, info overlays, tooltipsToasts, persistent notifications

Key Teaching Points

  • The Popover API does not add semantic roles — adding popover="auto" to a <div> does not make it a dialog. You must explicitly add role="dialog", role="tooltip", role="menu", or whatever role matches the content.
  • aria-expanded is handled automatically — the browser toggles aria-expanded on the popovertarget button when the popover opens and closes.
  • Light dismiss solves WCAG 1.4.13 “dismissible” — content shown via the Popover API can always be dismissed by pressing Escape or clicking outside.
  • Popover is not a dialog replacement — for content that requires a focus trap or blocks background interaction, use <dialog> with .showModal(). The Popover API is for lightweight overlays that do not block the page.
  • Baseline Widely Available — the Popover API reached Baseline Widely Available in April 2025 and is supported in Chrome, Edge, Firefox, and Safari.

Resources