unscripted/ui

Popover

A trigger and a free-form panel in the top layer — anchored under the button, light-dismissed, focus handled. Same machinery as the dropdown menu, pointed at arbitrary content.

popoveranchor positioningexit animations

Popover vs Dropdown Menu

Both float a panel in the top layer, both anchor under a trigger, both dismiss on Esc and outside click. The difference is the contents. A Dropdown Menu is a list of actions. A popover holds whatever you want: a little form, a set of controls, a preview. When the panel has inputs and labels rather than a column of commands, reach for this.

How it works

  • The popover attribute + popovertarget on the button give you top-layer rendering, toggling, Esc and click-outside dismiss. No JavaScript, no focus-trap library. Tab moves into the fields; Esc returns to the trigger.
  • CSS anchor positioning pins the panel under the button: [anchor-name:--pop-dimensions] on the trigger, then [position-anchor:--pop-dimensions] + [position-area:block-end_span-inline-end] on the panel (“below the anchor, growing to the right”).
  • [position-try-fallbacks:flip-block] flips the panel above when there’s no room below.
  • The inputs are plain <input>s. Because the panel lives in the top layer, they focus, type and tab exactly as they would in normal flow. The popover isn’t a rendering trick that traps them.

The fallback story

Without the Popover API the panel renders in normal document flow, always visible, and the button does nothing, so keep the markup somewhere sensible in the source order. Without anchor positioning the popover still opens, just centered in the viewport (the top-layer default) instead of pinned to the trigger; that’s why the base classes keep m-auto and only the offset is wrapped in a supports-[anchor-name:--a]: guard.

Browser support

Minimum stable version per engine, resolved at build time from MDN's browser-compat-data; Baseline status from the official web-features dataset. Everything degrades gracefully — the “when missing” column is the actual behavior, not a broken page.

FeatureChromeEdgeFirefoxSafariWhen missing
Popover APIBaseline 2025 · newly available11411412517Content renders in normal document flow, always visible, and the trigger does nothing.
CSS anchor positioningLimited availability12912914726The popover opens centered in the viewport (the top-layer default) instead of attached to its trigger.
Entry/exit animations (allow-discrete + @starting-style)Baseline 2024 · newly available11711712917.5Elements appear and disappear instantly. Nothing breaks — you just lose the animation.

† @supports cannot test at-rules, so the badge checks transition-behavior: allow-discrete, which co-shipped with @starting-style in every engine.