</> HTML5Advent
ENFRESDEITPT

// html · Web Platform Advent #16

The Popover API: native popups, menus and tooltips without a library

The HTML popover attribute and the Popover API let you build menus, tooltips and cards that render in the top layer, with light-dismiss and Esc handled for you - no JavaScript library needed.

Web page layouts open in a design app on a computer monitor

The Popover API is the browser's built-in answer to a problem every web developer has solved by hand a hundred times: showing a small piece of UI - a menu, a tooltip, a card, a notification - on top of everything else, and closing it again cleanly. With the popover attribute and a tiny JavaScript interface, you get the top layer, light-dismiss and Esc handling for free, no library required. Here is how it works.

The simplest popover

Any element becomes a popover by adding the popover attribute. A button opens it with popovertarget pointing at the popover's id:

<button popovertarget="menu">Open menu</button>

<div id="menu" popover>
  <p>I am a popover. Click outside or press Esc to close me.</p>
</div>

That is the whole thing. No click handler, no z-index, no outside-click listener. The browser renders the popover in the top layer (above the entire page, without z-index fights), and closes it when you press Esc or click outside.

auto vs manual

There are two kinds of popover, and the difference is who closes them:

<!-- auto: light-dismiss, only one open in a stack -->
<div id="tip" popover="auto">...</div>

<!-- manual: you open and close it yourself -->
<div id="toast" popover="manual">...</div>

An auto popover supports light-dismiss: Esc or an outside click closes it, and opening a new one closes the previous one in the same stack. A manual popover ignores all of that and stays open until your code hides it - the right choice for a toast or a persistent panel.

A code editor on a laptop showing an inline tooltip for a variable
A code editor showing an inline tooltip for a variable - exactly the kind of small overlay UI the Popover API now builds natively on the web.

Controlling it from JavaScript

When you need to open or close a popover in code, three methods do the job, plus a toggle event so you can react to state changes:

const menu = document.getElementById("menu");
menu.showPopover();     // open it
menu.hidePopover();     // close it
menu.togglePopover();   // flip it

menu.addEventListener("toggle", (e) => {
  console.log(e.newState); // "open" or "closed"
});

There is also a beforetoggle event that fires just before the state changes, which is handy for loading content lazily or running an entrance animation.

Styling and positioning

Style a popover while it is open with the :popover-open pseudo-class, and style the dimmed layer behind an auto popover with ::backdrop:

[popover]:popover-open {
  /* styles while the popover is shown */
}

[popover]::backdrop {
  /* the layer behind an auto popover */
  background: rgb(0 0 0 / 0.3);
}

To place a popover next to the button that opened it - like a real dropdown menu - pair it with CSS Anchor Positioning (anchor()) instead of measuring coordinates in JavaScript. The two features are designed to work together.

When to use it (and when not)

Reach for the Popover API for transient, overlay UI: dropdown menus, tooltips, teaching hints, small cards and notifications. For a blocking modal dialog that should trap focus and stop interaction with the page, the <dialog> element is still the better tool. Think of them as complements: popovers for lightweight overlays, dialogs for true modals.

The bottom line

The Popover API turns a pile of hand-written JavaScript - top-layer rendering, outside-click detection, Esc handling, focus juggling - into a single HTML attribute plus three methods. Use auto for menus and tooltips, manual for UI you control, style with :popover-open, and combine it with anchor positioning for real dropdowns. It is supported across modern browsers today, so most sites can adopt it without a polyfill.

Frequently asked questions

What is the Popover API?
The Popover API is a built-in browser feature for showing content on top of the page - menus, tooltips, cards, notifications - without a JavaScript library. You add the popover attribute to an element and point a button at it with popovertarget. The browser then handles rendering it in the top layer, closing it on Esc or an outside click, and the basic accessibility wiring.
What is the difference between auto and manual popovers?
An auto popover (popover or popover="auto") supports light dismiss: it closes when you press Esc or click outside it, and opening another auto popover closes the previous one in the same stack. A manual popover (popover="manual") does none of that - it stays open until your own code calls hidePopover(). Use auto for menus and tooltips, manual for things like toasts you control yourself.
Do I still need a dialog element or a library?
For most overlay UI - menus, tooltips, popcards - the Popover API replaces the JavaScript you used to write. For a true modal dialog that blocks the page and traps focus, the <dialog> element is still the better fit. And to position a popover next to its trigger, pair it with CSS Anchor Positioning rather than manual coordinate maths.
Is the Popover API supported in browsers?
Yes. The Popover API is part of the HTML standard and is supported across the major engines - Chromium-based browsers, Safari and Firefox. As always, check your own analytics, and for very old browsers you can add a small fallback, but for modern audiences it is safe to use directly.