Skip to content
← UI patterns

Popover

A non-modal panel anchored to a trigger, holding richer or interactive content and dismissed by clicking away or pressing Escape.

Click to open; click away or Esc to dismiss. It can hold a link, so it is a popover, not a tooltip.

Informational: a click-opened panel anchored to its trigger, light-dismissed by clicking away or pressing Escape, with focus returning to the trigger.

Holds focusable controls; the page behind stays interactive (non-modal).

Interactive: a popover holding a real form. Focusable content is exactly what separates a popover from a tooltip; the page behind is never blocked.

A menu of commands inside a popover, following the menu-button model.

Menu: a list of commands inside a popover. The overlay is a popover; the list follows the menu-button model with role=menu and menuitem.

Behavior

Keyboard

Enter / Space
Activates the trigger to open or toggle the popover.
Tab / Shift+Tab
Moves through the popover's interactive content, which is placed next in the tab order, then continues to the rest of the page since focus is not trapped.
Escape
Light-dismisses an auto popover and returns focus to the trigger.
Parts

Trigger / invoker

The control that opens the popover, a real <button>. Using the native popovertarget attribute wires an implicit aria-expanded and aria-details relationship and the correct focus order and restoration automatically.

Panel

The overlay container holding the content. With the popover attribute it is promoted to the top layer so it renders above other content without z-index conflicts, and in auto mode it light-dismisses on outside click or Escape.

Content (possibly interactive)

What the popover reveals: text, a menu, a small form, a date or color picker. Unlike a tooltip, a popover may contain focusable, interactive elements, which is the line that separates the two patterns.

Role and label

The popover attribute adds no implicit role, so the panel must declare its own: role=dialog with aria-modal=false for a non-modal dialog, role=menu for a menu, or a labeled group. Give it an accessible name to match.

Anchor and arrow

CSS anchor positioning ties the panel to the trigger via anchor-name and position-anchor and supplies fallback positions so it flips instead of overflowing the viewport. An optional arrow visually connects the panel to its trigger.

States

Open and light-dismiss

An auto popover opens from its trigger and is dismissed by clicking outside it or pressing Escape, with no explicit close button required. Showing one auto popover closes any other that is open, so they do not stack up.

Focus on open and close

When an auto popover opens, the keyboard tab order is updated so the controls inside come next; closing it with the keyboard (typically Escape) returns focus to the trigger. Focus is not trapped, the defining contrast with a modal dialog.

Anchored positioning and collision

The panel is positioned relative to its trigger with CSS anchor positioning, and given fallback positions so that when it would overflow its container or the viewport the browser flips it, for example from above the trigger to below, instead of clipping.

Manual versus auto

An auto popover light-dismisses and auto-closes siblings; a manual popover does neither and stays open until explicitly toggled. Choose manual only for cases that must persist through outside interaction, since it forfeits the convenient dismissal users expect.

Escalate to a dialog when needed

If the content must block the rest of the page, demand a deliberate decision, or trap focus until resolved, it is no longer a popover but a modal dialog, which inertizes the background and keeps focus inside until dismissed.

References

MDN Popover API documentation page describing non-modal popovers shown in the top layer.
The Popover APIMDN Web Docs
MDN guide on using CSS anchor positioning, showing an element positioned relative to an anchor.
Using CSS anchor positioningMDN Web Docs

Use it

Figma
An anchored popover with directional variants
  1. Build the panel as an Auto Layout frame with padding and a soft shadow; add a small rotated square as the arrow on a separate layer.
  2. Make a component set with a Placement property: Top, Right, Bottom, Left, moving the arrow to the edge facing the trigger in each.
  3. Set a sensible max width so content wraps rather than stretching the panel into a strip.
  4. Expose surface and border colors as variables so a themed page can restyle every popover at once.

Pin the arrow with constraints so switching the Placement variant moves only the arrow, not the content.

An interactive popover with a small form
  1. Place real controls inside the panel: a labeled field, a couple of options, and Apply and Cancel buttons in an Auto Layout column.
  2. Add focus-state variants to the inner controls so the keyboard path through the panel is visible.
  3. Show an open state anchored to its trigger button, with the rest of the page still visible behind it.
  4. Annotate that the panel needs role=dialog with aria-modal=false (or a labeled group) and that focus is not trapped, in the build.

Keep the page content visible and ungrayed behind the panel to communicate that a popover is non-modal, unlike a dialog.

Prototype open and light-dismiss
  1. Hide the panel, then add an On Click interaction from the trigger that opens it as an overlay positioned next to the trigger.
  2. Set the overlay to close when clicking outside, mirroring auto light-dismiss.
  3. Add a short Dissolve so it fades rather than snaps, and note reduced-motion handling.
  4. Annotate that Escape must also dismiss and return focus to the trigger in the build, which a Figma prototype cannot fully show.

Use the overlay's click-outside-to-close setting to model light-dismiss, and call out Escape in a note since prototypes ignore it.

Document popover versus tooltip versus dialog
  1. Lay three labeled examples side by side: a hover tooltip, a click popover with controls, and a modal dialog over a dimmed page.
  2. Caption the tooltip as text-only, non-focusable, hover/focus.
  3. Caption the popover as anchored, interactive, non-modal, light-dismissed.
  4. Caption the dialog as blocking and focus-trapping, and add the one-line rule for choosing between them.

Keep this trio in the team library so the overlay decision is made once, not re-argued per feature.

Accessibility

A popover is non-modal: it does not trap focus or block the page, and auto popovers dismiss on outside click or Escape. Wire the trigger with popovertarget so aria-expanded, the aria-details relationship, and focus restoration are handled for you. Because the popover attribute adds no role, give the panel the right one for its content (dialog with aria-modal=false, menu, or labeled group) and an accessible name. When the content must block the page, use a modal dialog instead.

  1. Keep auto-dismiss working: Escape and outside click should close the popover and restore focus to the trigger.
  2. Ensure all interactive content inside is keyboard reachable and that the tab order flows in and back out naturally.
  3. Position with fallbacks so the panel flips rather than overflowing, and never let it cover its own trigger when that matters.
  4. Meet contrast and target-size requirements for the panel and its controls, and respect reduced-motion for open/close animation.
  5. Choose the pattern deliberately: text-only is a tooltip, must-block is a modal dialog, anchored-and-dismissible is a popover.
Research notes & sources

No dedicated role: the popover attribute adds none, so apply role=dialog (aria-modal=false), menu, or a labeled group to match the content; popovertarget wires implicit aria-expanded and aria-details

  1. Popover APIMDN Web Docs
  2. Using the Popover APIMDN Web Docs
  3. Using CSS anchor positioningMDN Web Docs
  4. Dialog (Modal) Pattern (ARIA Authoring Practices Guide)W3C WAI
  5. Tooltips in the time of WCAG 2.1