Popover
CSS styling for native HTML popover attribute. Provides top-layer positioning, light dismiss, and keyboard support without JavaScript. This is a low-level primitive—for most use cases, prefer higher-level components like Modal, Dropdown, or Tooltip.
- Modal (Tier 2) - Blocking dialogs with focus trap and backdrop
- Dropdown (Tier 3) - Action menus with keyboard navigation
- Tooltip (Tier 3) - Accessible hints with proper ARIA
- Bottom Drawer (Tier 3) - Mobile-friendly sheets
Example
Click outside or press Escape to close.
<button class="omni-button" popovertarget="example-popover">
Open Popover
</button>
<div popover id="example-popover" class="omni-popover">
<p>Click outside or press Escape to close.</p>
</div>
Capabilities
What Native Popover Provides
- Top layer rendering (no z-index issues)
- Light dismiss (click outside closes)
- Escape key closes
- Works without JavaScript
- Smooth entrance animations
What Native Popover Does NOT Provide
- Any semantic ARIA role
- Focus trapping
- Backdrop/overlay
- Keyboard navigation within content
- Automatic positioning relative to trigger
Variants
Position Variants
Use data-position to control animation origin. Note: This only affects the animation origin, not the actual positioning (which you must handle via CSS or JavaScript):
<div popover class="omni-popover" data-position="top">...</div>
<div popover class="omni-popover" data-position="bottom">...</div>
<div popover class="omni-popover" data-position="left">...</div>
<div popover class="omni-popover" data-position="right">...</div>
Size Variants
Use data-size to control width constraints:
<div popover class="omni-popover" data-size="sm">Small</div>
<div popover class="omni-popover">Medium (default)</div>
<div popover class="omni-popover" data-size="lg">Large</div>
Adding ARIA Roles
Since native popover doesn't provide semantic meaning, you must add appropriate ARIA based on your content:
Interactive Content (Dialog Pattern)
This popover has role="dialog" for accessibility.
For real dialogs, use Modal (Tier 2) instead.
<div popover class="omni-popover"
role="dialog"
aria-labelledby="dialog-title">
<h3 id="dialog-title">Settings</h3>
<!-- Interactive content -->
</div>
role="dialog"+aria-labelledbyfor interactive contentrole="menu"for action lists (but use Dropdown instead)role="listbox"for selection lists (but use Combobox instead)role="tooltip"for hints (but use Tooltip instead)
CSS-Only Limitations
- No automatic positioning: You must manually position the popover using CSS
insetproperties or JavaScript. The native API doesn't calculate optimal placement relative to the trigger button. - No focus management: Focus doesn't automatically move to the popover. For interactive content, add
autofocusto the first focusable element. - No collision detection: Won't automatically reposition if it overflows viewport. Use CSS anchor positioning (where supported) or JavaScript.
- Mobile behavior: On mobile, position variants are overridden to use top-center origin for consistency.
API Reference
| Attribute | Values | Default | Description |
|---|---|---|---|
popover |
— | — | Native HTML attribute (required) |
id |
string | — | Unique ID referenced by popovertarget |
data-position |
top, bottom, left, right | — | Animation origin (not actual position) |
data-size |
sm, md, lg | md | Width constraints |
Trigger Button Attributes
| Attribute | Values | Description |
|---|---|---|
popovertarget |
ID of popover | Links button to popover element |
popovertargetaction |
toggle, show, hide | Action to perform (default: toggle) |
Accessibility
- Native popover provides Escape key dismiss behavior
- Light dismiss (click outside) built into native API
- Rendered in top layer, avoiding z-index issues
- Must add
roleattribute based on content type - Must add
aria-labelledbyoraria-labelfor dialogs - Consider adding
autofocusto first interactive element - No focus trap—users can tab out of the popover
- Respects
prefers-reduced-motionfor animations
Browser Support
Native Popover API Support:
- Chrome/Edge 114+
- Safari 17+
- Firefox 125+
For older browsers, the popover will render as a regular div. Consider using a polyfill or fallback to higher-level components like Modal.
Components Used
Other OmniUI components demonstrated on this page: