Popover
A native popover built with the popover attribute and declarative popovertarget buttons. The browser handles the top layer, light dismiss, Escape closing, and open state without custom JavaScript.
0 KB JavaScript
~40 CSS lines
popover declarative controls
dismiss native light dismiss
Preview
Contextual popover
A popover floats above the page, closes on outside click or with Esc, but does not block the interface behind it. Perfect for a menu, help text or a secondary panel.
Light action
This panel can accompany a low-risk action, without interrupting the whole page like a modal would.
The code
The markup
<button type="button" popovertarget="info-popover">
Open popover
</button>
<div id="info-popover" popover="auto" class="popover" aria-labelledby="popover-title">
<div class="popover-inner">
<button class="popover-close" type="button" popovertarget="info-popover" popovertargetaction="hide" aria-label="Close">×</button>
<h2 id="popover-title">Contextual popover</h2>
<!-- content -->
<button type="button" popovertarget="info-popover" popovertargetaction="hide">Got it</button>
</div>
</div>CSS mechanisms
/* ----------------------------------------------------------------------------
* Popover
* ---------------------------------------------------------------------------- */
/**
* Native popover panel.
*
* The popover element stays visually neutral and moves into the
* top layer when opened. Use `.popover-inner` for the visible
* surface and custom presentation styles.
*/
.popover {
margin: auto;
overflow: visible;
/* add your styles here */
}
/**
* Visible popover content wrapper.
* Use this element for custom spacing, surface, border, shadow, etc.
*/
.popover-inner {
/* add your styles here */
}
/* ----------------------------------------------------------------------------
* Popover close button
* ---------------------------------------------------------------------------- */
/**
* Explicit close control.
*/
.popover-close {
/* add your styles here */
}
/* ----------------------------------------------------------------------------
* Popover Animation (Top Layer)
* ---------------------------------------------------------------------------- */
/**
* Closed-state styling for the popover panel.
*
* Uses the new `transition-behavior` / `allow-discrete` mechanism
* so the `display: none → block` and top-layer `overlay` changes
* animate smoothly instead of snapping. Without `allow-discrete`,
* the popover would appear and disappear instantly.
*/
.popover {
opacity: 0;
transition:
opacity 240ms,
overlay 240ms allow-discrete,
display 240ms allow-discrete;
}
/**
* Open state: full opacity.
*
* `:popover-open` only matches the popover while it is showing.
*/
.popover:popover-open {
opacity: 1;
}
/**
* Initial keyframe override: required so the entrance transition
* runs on the first open after the discrete `display` change.
*/
@starting-style {
.popover:popover-open {
opacity: 0;
}
}
/**
* Backdrop transition hook.
*
* Add a background here if you want a visible overlay.
*/
.popover::backdrop {
opacity: 0;
transition:
opacity 240ms,
overlay 240ms allow-discrete,
display 240ms allow-discrete;
}
/**
* Open backdrop becomes visible.
*/
.popover:popover-open::backdrop {
opacity: 1;
}
/**
* Initial keyframe override for the backdrop, same reason as above.
*/
@starting-style {
.popover:popover-open::backdrop {
opacity: 0;
}
}Benefits
-
01.
Declarative markup
The relationship between the button and panel is declared in HTML with
popovertarget. No custom click handler is needed. -
02.
Native top layer
The browser places the popover above the page content, avoiding manual
z-indexstacking and portal-style workarounds. -
03.
Light dismiss
With
popover="auto", the panel can close on outside click or Esc, using built-in browser behavior. -
04.
Low runtime cost
No JavaScript state, no hydration, no re-rendering. Opening, closing, and visible state are handled by the platform.
Current limitations
-
01.
Non-modal behavior
Popovers do not make the rest of the page inert. For blocking flows, confirmations, or required decisions, use a native
<dialog>. -
02.
Positioning control
The basic popover API handles visibility, not advanced placement. Anchored positioning may require newer CSS or a custom layout strategy.
-
03.
Exit animation support
Smooth top-layer exit depends on
overlaywithallow-discrete. Without full support, the popover still works but may close instantly.