Native Overlay
Uses <dialog>.showModal(). Top-layer rendering ✓, Escape to close ✓, scroll locking ✓, and the ::backdrop pseudo-element.
::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 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.
Scroll locking is still missing: the background remains scrollable while open.
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.
| 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.
popovercomes closest, but lacks scroll locking, a positioning engine, and complex state managementdialog.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.