Popover vs. Dialog: Sorting Out the Semantics

The relationship between the Popover API (popover attribute) and Dialogs (the <dialog> element or the dialog ARIA role) confuses many developers. The confusion is understandable, but a clear mental model resolves it: a dialog is not a competitor to a popover — it is a specific type of popover.

Dialog Is a Subset of Popover

Consider how popups are categorized in the ARIA specification. The aria-haspopup property, which indicates that an element triggers a popup, lists five possible values for the popup’s role:

  • menu
  • listbox
  • tree
  • grid
  • dialog

(A sixth value, true, is equivalent to menu.) Since dialog appears on that list, the specification itself treats a dialog as one kind of popover.

Dialogs Break Down Into Three Varieties

Within the umbrella of dialogs, there are three categories:

  • Modal: Shows an overlay and traps focus.
  • Non-modal: Uses neither an overlay nor focus trapping.
  • Alert dialog: Notifies screen readers when displayed; can be modal or non-modal.

Some argue that popovers are inherently non-modal, but that position fails against a key detail: the ::backdrop pseudo-element. Because a popover or dialog on the top layer can render a backdrop that covers the viewport, popovers can be modal. The presence of ::backdrop is a strong indication of modality rather than a guarantee of non-modality.

Still, the Popover API is not recommended for building a true modal. It lacks the showModal() method available on <dialog>, which handles inertness and focus trapping. Recreating those features manually is error-prone when a <dialog> already provides them.

Assigning a Role to a Popover

Accessible popovers need an explicit role. The safest options are the ones defined by aria-haspopup:

  • menu
  • listbox
  • tree
  • grid
  • dialog

More complex roles also work: treegrid and alertdialog. Two additional roles — tooltip and status — are valid but more contentious. Crucially, they cannot be paired with aria-haspopup.

The Tooltip Exception

Visually, a tooltip is a popover: a small window that appears on demand. It is reasonable to implement one with the Popover API. However, the tooltip role differs from the others in a fundamental way: tooltips must not contain interactive content. If a tooltip needs interactive elements, it stops being a tooltip and becomes a dialog.

This distinction explains why aria-haspopup omits tooltip: the attribute signals interactive popups, and an accessible tooltip is never interactive. Because the tooltip role does not do much in screen readers today, an accessible tooltip requires pairing with aria-describedby.

Why Status Works for Toggletips

Tooltips conventionally appear only on hover, which leaves screen reader and touch device users without access. The toggletip pattern addresses this by using live regions to announce the content. A toggletip’s bubble is populated into an empty live region when invoked, both displaying it visually and causing the region to announce it.

The status role fits that pattern. It is a live region role, which sets it apart from the other popover roles. It is a valid choice for a popover used in a toggletip context, but applying it requires care and discretion.

A Working Mental Model

The umbrella-term view simplifies decisions:

  • Popover: any on-demand popup, regardless of implementation.
  • Dialog: one flavor of popover — a new window or card containing some content.

That perspective also explains why the Popover API can work alongside the dialog element without conflict.

When selecting a role for a popover, the reliable options are menu, listbox, tree, grid, treegrid, dialog, and alertdialog. Most of these integrate with aria-haspopup, which has seen decent screen reader support. The status and tooltip roles are situational and cannot accompany aria-haspopup — but knowing when they apply puts the full popover taxonomy at your disposal.