Popover API lands in Baseline

It's happening! One of the features I am most hyped about has just landed across all modern browsers and is officially a part of Baseline 2024. And this feature is the Popover API. Popover provides so many awesome primitives and developer affordances for building layered interfaces like tooltips, menus, teaching UIs, and more.

Browser Support

  • Chrome: 114.
  • Edge: 114.
  • Firefox: 125.
  • Safari: 17.

Source

Some quick highlights of popover capabilities include:

  • Promotion to the top layer. Popovers will appear in the top layer above the rest of the page, so you don't have to play around with z-index.
  • Light-dismiss functionality. Clicking outside of the popover area will close the popover and return focus.
  • Default focus management. Opening the popover makes the next tab stop inside the popover.
  • Accessible keyboard bindings. Hitting the esc key or double toggling will close the popover and return focus.
  • Accessible component bindings. Connecting a popover element to a popover trigger semantically.

Creating popovers

Creating popovers is quite straightforward. To use default values, all you need is a button to trigger the popover, and an element to trigger.

  • First, set a popoverattribute on the element which is going to be the popover.
  • Then, add an unique id on the popover element.
  • Finally, to connect the button to the popover, set the button's popovertargetto the value of the popover element's id.

This is shown in the following code:

<button popovertarget="my-popover">Open Popover</button>

<div id="my-popover" popover>
  <p><p>I am a popover with more information. Hit <kbd>esc</kbd> or click away to close me.<p></p>
</div>
A basic example of using the popover attribute.

To have more granular control over the popover, you can explicitly set types of popovers. For example, using a bare popover attribute with no value is the same as popover="auto". The auto value enables light-dismiss behavior and automatically closes other popovers. Use popover="manual" and you will need to add a close button, manual popovers don't close other popovers or allow users to dismiss the popover by clicking away in the UI. You create a manual popover using the following:

<button popovertarget="my-popover" class="trigger-btn"> Open Popover </button>

<div id="my-popover" popover=manual>
  <p>I am a popover with more information. Hit the close button or toggle to close me.<p>
  <button class="close-btn" popovertarget="my-popover" popovertargetaction="hide">
    <span aria-hidden="true">❌</span>
    <span class="sr-only">Close</span>
  </button>
</div>
An example of a manual popover.

Popover versus modal dialog

You may be wondering if you need popover when dialog exists, and the answer is: you might not.

It's important to note that the popover attribute does not provide semantics on its own. And while you can now build modal dialog-like experiences using popover, there are a few key differences between the two:

The modal <dialog> element

  • Opened with dialog.showModal().
  • Closed with dialog.close().
  • Makes the rest of the page inert.
  • Does not support light-dismiss behavior.
  • You can style the open state with the [open] attribute.
  • Semantically represents an interactive component that blocks interaction with the rest of the page.

The [popover] attribute

  • Can be opened with a declarative invoker (popovertarget).
  • Closed with popovertarget (auto popover) or popovertargetaction=hide (manual popover).
  • Does not make the rest of the page inert.
  • Supports light-dismiss behavior.
  • You can style the open state with the :popover-open pseudo-class.
  • No inherent semantics.

Conclusion and further reading

There are many exciting features that popover brings to the platform. To learn more about this API, including more on the accessibility of the feature, and documentation regarding the feature set, here is some recommended reading for further information: