ComponentsPopover patterns

Menus, hints and cards built on the native popover attribute and placed with CSS anchor positioning.

On this page

Popover patterns are new in Pico Reforged and not part of Pico CSS v2.1.1. They are opt-in and additive: the v2.1.1 markup (details.dropdown, data-tooltip) still works, and every pattern here has a plain fallback. The CSS lives in components/popover, with no extra file to load.

A popover is any element with the popover attribute. The browser puts it in the top layer, handles Escape and clicks outside, and hides it until it is opened. A button with popovertarget opens it, no script needed.

A <ul popover> (or <menu popover>) next to a button is a dropdown menu. It drops below the button and aligns to its start edge.

Menu popover
<button popovertarget="menu">Actions</button>
<ul popover id="menu">
  <li><a href="#edit">Edit</a></li>
  <li><a href="#duplicate" aria-current="page">Duplicate</a></li>
  <li><a href="#archive">Archive</a></li>
</ul>

The menu is at least 10rem wide, or as wide as the button if that is larger. More in Dropdown.

Hint

popover="hint", or popover with role="tooltip", is the tooltip bubble. It sits above its trigger and flips below if it does not fit. The script that shows it on hover and focus is on the Tooltip page.

Card

A popover that contains an <article> loses its own frame, and the article is the card, header and footer included. A popover with no article gets the card surface itself: padding, border, radius and shadow.

Card popover
<button popovertarget="note">Open note</button>
<div popover id="note" style="position-area: block-end; inset: auto; margin-block: 0.5rem">
  <article>
    <header><strong>Heads up</strong></header>
    <p>A popover with an article inside looks like a card.</p>
    <footer>
      <button popovertarget="note" popovertargetaction="hide">Got it</button>
    </footer>
  </article>
</div>

The style attribute on the card places it with anchor positioning. Menus and hints get this from the stylesheet. Cards and other popovers are left to the browser, which centers them in the viewport unless you place them.

Anchor positioning

When a popover is opened from a button with popovertarget, the button is its implicit anchor. The stylesheet uses that for menus and hints:

CSS
:is(ul, menu)[popover] {
  position-anchor: auto;
  inset: auto;
  position-area: block-end span-inline-end;
  position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
}

position-area says which side of the anchor to use, and position-try-fallbacks flips it when it would overflow. To move a popover, set position-area on it. For example, a menu that opens above the button and grows toward the start edge:

CSS
#menu {
  position-area: block-start span-inline-start;
}

To anchor to something other than the invoker, name it and point at the name:

CSS
.toolbar-button {
  anchor-name: --toolbar;
}

#menu {
  position-anchor: --toolbar;
}

All of this sits behind @supports (anchor-name: --a) and (position-area: top).

Opening from script

A popover opened with showPopover() has no invoker unless you pass one, so give it a source for the anchor. The source option is newer than popover itself, so the call is harmless where it is ignored.

JavaScript
menu.showPopover({ source: button });

Fallbacks

Newer features are additive. Where a floor browser does not support one, the page still works:

FeatureWithout support
Popover and popover="hint"the element shows as normal content
Anchor positioningpopovers open in the top layer with fixed placement
@starting-style and transition-behaviorno open or close animation

The fade and small slide on open and close are wrapped in prefers-reduced-motion: no-preference. The full table and the browser floor (Chrome and Edge 111, Firefox 128, Safari 16.4) are on Browser support.

Accessibility

popovertarget links the button and the popover for assistive technology, and Escape closes an auto popover. Keep menus to links and form controls, keep hints short and out of the tab order, and use modal when the person must answer before going on.

Customization

Menus read the dropdown tokens, hints read the tooltip tokens and cards read the card tokens.

--pico-dropdown-background-color
light-dark(#ffffff, #1c1e22)
Menu surface.
--pico-dropdown-border-color
light-dark(#e3e4e8, #313337)
Menu border.
--pico-dropdown-hover-background-color
light-dark(#f2f3f6, #292b2f)
Hovered or current menu item.
--pico-tooltip-background-color
light-dark(#1c1f25, #2b2e33)
Hint bubble.
--pico-tooltip-color
light-dark(#ffffff, #edeef1)
Hint text.
--pico-card-background-color
var(--pico-background-color)
Surface of a popover without an article.
--pico-card-box-shadow
var(--pico-box-shadow)
Shadow of a popover without an article.