Skip to content

Popover

.bp-popover uses the browser’s native Popover API — the [popover] attribute and popovertarget wiring do all the show/hide work. No JavaScript required. The popover renders in the top layer above all other content, so overflow and z-index are never an issue.

Entry and exit are animated with @starting-style for a smooth fade-slide.

Basic popover

Popover title

This is the popover content. It can include any HTML.

<button class="bp-btn bp-btn--outline" popovertarget="demo-pop-1">
Open popover
</button>
<div id="demo-pop-1" class="bp-popover" popover>
<div class="bp-popover__header">
<h3 class="bp-popover__title">Popover title</h3>
<button class="bp-popover__close" popovertarget="demo-pop-1" popovertargetaction="hide" aria-label="Close"></button>
</div>
<p>This is the popover content. It can include any HTML.</p>
</div>

With actions

Confirm delete

This action cannot be undone. The item will be permanently deleted.

<button class="bp-btn bp-btn--primary" popovertarget="demo-pop-2">
Delete item
</button>
<div id="demo-pop-2" class="bp-popover" popover>
<div class="bp-popover__header">
<h3 class="bp-popover__title">Confirm delete</h3>
<button class="bp-popover__close" popovertarget="demo-pop-2" popovertargetaction="hide" aria-label="Close"></button>
</div>
<p>This action cannot be undone. The item will be permanently deleted.</p>
<div class="demo-popover-actions">
<button class="bp-btn bp-btn--ghost" popovertarget="demo-pop-2" popovertargetaction="hide">Cancel</button>
<button class="bp-btn bp-btn--danger">Delete</button>
</div>
</div>
VariableDefaultDescription
--popover-bg--bp-color-bg-elevatedBackground color
--popover-border1px solid --bp-color-borderBorder
--popover-radius--bp-radius-lgBorder radius
--popover-shadow--bp-shadow-lgBox shadow
--popover-padding--bp-space-4Inner padding
--popover-width20remMax width
--popover-bg (backdrop)30% text colorSet ::backdrop color via color-mix
No axe violations tested 2026-05-11
  • The native Popover API handles focus management automatically — when the popover opens, focus moves into it; when it closes, focus returns to the trigger.
  • The popover is dismissed by pressing Escape — built in by the browser.
  • Add aria-expanded to the trigger button if you need to reflect open state for screen readers: wire it with a small JS listener on toggle event.
  • Use popovertargetaction="hide" on the close button to avoid toggling.
APIAvailabilityUsed forWithout it
Popover API Newly available Baseline 2024 Show/hide, top layer, focus managementJS + dialog fallback
@starting-style Newly available Baseline 2024 Entry animationNo entry animation
allow-discrete transitions Newly available Baseline 2024 Exit animation on display: noneNo exit animation

The popover is hidden and shown purely by the browser via [popover] attribute — no display toggling in JS needed. The @starting-style block defines the pre-open state so the browser can transition from it on entry. Exit animation uses transition: display allow-discrete which lets CSS animate during the frame before display: none is applied.

The popover renders in the top layer — a browser-managed stacking context above everything else — so it never gets clipped by overflow: hidden or lost under other elements.