Molecules
Popover
A layer anchored to the control that opens it, holding a Card or a Menu.
Orders placed before noon leave the same day.
Code
<button type="button" class="button" popovertarget="default-popover">
<span>Delivery details</span>
<svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#ChevronDown"/></svg>
</button>
<div id="default-popover" popover class="popover">
<div class="card card--compact">
<div class="card__body">
<p class="text">Orders placed before noon leave the same day.</p>
</div>
</div>
</div>
Why it exists
Some things belong to one control and only matter for a moment: the actions behind a Button, a short form, a preview of a person. A Popover holds them next to that control and leaves the rest of the page usable, which is what separates it from a Dialog.
It uses the native popover attribute. The browser puts it in the top layer, closes it on Escape or a click outside, and tells assistive technology whether it is open. The control that opens it is its anchor, so the markup doesn’t wire them together, and it flips to the other side when it doesn’t fit. None of that needs a script.
It has no surface of its own. What’s inside is a Card or a Menu, built the way they are everywhere else, and the Popover only decides where they go.
When to use
- For a Card or a Menu that belongs to one control: actions, a short form, a preview.
- Not for a short line of plain text about a control: that is a Tooltip.
- Not for a task that must block the page: that is a modal Dialog.
- Not for a message about the page or a result: that is a Banner or a Toast.
Rules
- Opening.
popovertargetopens it on click.interestforopens it on hover and focus, as a Hovercard; that works in Chromium only, so a Hovercard never holds the only way to reach something. Escape and a click outside close it. - Content is a Card or a Menu, nothing else. A tall Card shrinks to the screen; give it
.card__body--scrollable, focusable and named. - A Card with a
<header>is an<article>. In a<div>, that header can become the page’s banner landmark. - Roles. The Popover takes no role and its invoker no
aria-haspopup;popovertargetalready exposes the expanded state. A Popover holding a Form or several controls under a title may takerole="dialog"witharia-labelledby, and its invoker then saysaria-haspopup="dialog". A list of actions is a Menu.
Keyboard and screen readers
The browser provides all of this for a Popover opened with popovertarget. Script only what the controls inside it do.
- Enter and Space on the Button open and close it.
- Focus stays on the Button when it opens, unless something inside has
autofocus. - Tab moves on from the Button. Keep the Popover right after its Button in the source, as these examples do, so Tab goes straight into it.
- Escape closes it and returns focus to the Button if focus was inside. A click outside closes it too.
- A screen reader hears the Button as expanded or collapsed. Opening a Popover announces nothing else, so it needs a Button label that says what it opens.
- A control inside doesn’t close it. Give a closing Button
popovertargetandpopovertargetaction="hide", or callhidePopover()from the script that does the work.
A few actions under a title
Document
Code
<button type="button" class="button" popovertarget="doc-actions">
<span>Actions</span>
<svg class="icon" width="1em" height="1em" aria-hidden="true" focusable="false"><use href="#ChevronDown"/></svg>
</button>
<div id="doc-actions" popover class="popover">
<article class="card card--compact card--ruled">
<header class="card__header"><h3 class="card__title heading">Document</h3></header>
<div class="card__body stack" style="--button-prominence: subtle;">
<button type="button" class="button"><span>Duplicate</span></button>
<button type="button" class="button"><span>Export JSON</span></button>
<button type="button" class="button button--danger"><span>Delete</span></button>
</div>
</article>
</div>
A Card suits a few actions that need a title. For a longer list, with headings and shortcuts, use a Menu.
A Form Under a Title
Preferences
Code
<button type="button" class="button" popovertarget="prefs" aria-haspopup="dialog"><span>Settings</span></button>
<div id="prefs" popover class="popover" role="dialog" aria-labelledby="prefs-title">
<article class="card card--compact card--ruled">
<header class="card__header"><h3 class="card__title heading" id="prefs-title">Preferences</h3></header>
<div class="card__body stack">
<div class="field">
<label for="prefs-name" class="field__label label">Display name</label>
<input id="prefs-name" type="text" class="input" />
</div>
</div>
<footer class="card__footer">
<button type="button" class="button button--strong button--accent button--sm" popovertarget="prefs" popovertargetaction="hide"><span>Done</span></button>
</footer>
</article>
</div>
A Form is more than a list of actions, so this one is a labelled Dialog to assistive technology, without being modal. Its Done Button closes it with popovertargetaction="hide".
A preview on hover and focus
Jordan Lee
Accessibility lead
Code
<a class="link" href="/people/jordan" interestfor="hc-jordan">Jordan Lee</a>
<div id="hc-jordan" popover class="popover">
<article class="card">
<header class="card__header">
<hgroup class="card__hgroup">
<h3 class="card__title heading">Jordan Lee</h3>
<p class="card__subtitle small-text">Accessibility lead</p>
</hgroup>
</header>
<footer class="card__footer"><a class="link" href="/people/jordan">View profile</a></footer>
</article>
</div>
The Link still goes to the profile, so someone in a browser without interestfor, or on a touch screen, only misses the preview.
Do and Don’t
| Do | Don’t |
|---|---|
| Put a Card or a Menu in a Popover. | Put bare text or a Banner in one. |
| Let the invoker be the anchor. | Add anchor-name or position-anchor to the markup. |
| Keep another way to reach what a Hovercard holds. | Put the only route to something in interestfor, which works in Chromium only. |
Add role="dialog" and aria-labelledby for a Form under a title. | Add aria-haspopup to a Popover that isn’t a Dialog. |
| Use a Tooltip for a short line about a control. | Use a Popover for it. |
In Storybook
See also
- Menu: A list of actions in rows, usually opened from a Button in a Popover.
- Card: A surface with named parts, such as a header, a body and a footer, for one thing a person can read, compare or act on.
- Tooltip: A short line of plain text about a control, shown while the control is hovered or focused.
- Dialog: A modal window on top of the page, for a decision, a short form or a drawer of settings.