Native Overlay

Native Dialog (showModal)

Uses <dialog>.showModal(). Top-layer rendering ✓, Escape to close ✓, scroll locking ✓, and the ::backdrop pseudo-element.

Native Dialog

showModal() automatically prevents background scrolling.
Open the dialog and try scrolling the background.

Findings: Scroll locking works out of the box.
::backdrop supports an entrance animation, but cannot animate its exit: the browser immediately removes ::backdrop on close(). This is an API limitation.
No anchor positioning: it supports centered dialogs rather than anchored dropdowns, menus, or popovers.
floating-ui + Native Popover (left flip)

floating-ui computes the position with left placement. The HTML popovertarget attribute links the trigger and popover.

Left Positioned

floating-ui computePosition + flip + shift.
Flips to the right when there is not enough space on the left.

Findings: Positioning and light dismiss both work.
Scroll locking is still missing: the background remains scrollable while open.
Native Popover (popover attribute)

Uses the browser's native popover attribute. Top-layer rendering ✓, light dismiss ✓, and anchor positioning through CSS anchors or JavaScript.

popover + floating-ui

The browser handles top-layer rendering and light dismiss.
floating-ui handles anchor positioning and collision detection.

Top Placement

placement=top. Scroll to the bottom of the page and open it to test flipping.

Findings: Native popovers do not prevent background scrolling. Open a popover above and scroll the page; the body still scrolls. CSS anchor positioning works without floating-ui, but browser support is limited (Chrome only), and collision detection is missing.
Comparison
Capability popover dialog.showModal popover + floating-ui ark/zag + Overlay
Top-layer rendering ✓ ✓ ✓ ✓ (Portal)
Anchor positioning △ (CSS anchors, limited) ✗ ✓ ✓
Collision detection △ (position-try) ✗ ✓ ✓
Light Dismiss ✓ ✓ (Escape) ✓ ✓ (state machine)
Scroll locking ✗ ✓ ✗ ✓ (preventBodyScroll)
Android back gesture ? ? ? ✓ (CloseWatcher)
Nested overlays △ (popovers are global) △ (nesting unsupported) △ ✓ (overlay stack)

Conclusion: No single native API covers all dropdown overlay requirements.

  • popover comes closest, but lacks scroll locking, a positioning engine, and complex state management
  • dialog.showModal() locks scrolling but cannot position against an anchor, so it suits modal dialogs
  • ark-ui/zag-js with our Overlay is currently the only option that covers every capability in this comparison

Future possibilities: If browsers add the proposed lock-scroll attribute to popovers and make @position-try, anchor(), position-area as reliable as floating-ui, they could replace the ark/zag positioning layer. State machines would still be needed for nesting, open/close transitions, and keyboard navigation.