Because for twenty years the browser gave us nothing to build them with. Every menu, tooltip, and toast had to be assembled by hand from a div, a z-index, a click listener, an escape key handler, and a focus trap. Everyone rebuilt the same thing, and everyone got some part of it wrong.
That is the honest history of front-end work. A pattern that looks trivial to a client turns into two hundred lines of JavaScript, and then a bug report six months later because the menu does not close when you click outside it on iOS. We have all shipped that bug.
The Popover API is the browser finally taking the job back. It is small, it is native, and it removes a category of code most sites should never have been writing.
The Popover API is a browser feature for showing content on top of other content, using HTML attributes instead of JavaScript. MDN describes it as "a standard, consistent, flexible mechanism for displaying popover content on top of other page content." Popovers are always non-modal, so the rest of the page stays interactive.
MDN lists the typical uses as "action menus, custom 'toast' notifications, form element suggestions, content pickers, or teaching UI." That covers most of what a marketing site or a product dashboard actually needs. It is not a modal system, and that distinction matters more than it sounds.
The feature reached Baseline in 2025. According to MDN, "since January 2025, this feature works across the latest devices and browser versions." That is a meaningful line to cross, because it means Chrome, Safari, Firefox, and Edge all shipped it, not just the Chromium browsers.
Baseline is the web platform's shared vocabulary for browser support. It sorts features into three buckets. Limited availability means not all major browsers support it. Newly available means every Baseline browser supports it in its latest stable version. Widely available means that support has held for a long time.
The exact threshold is worth knowing, because it changes how you plan. MDN defines widely available features as those with "a consistent history of support in each of the Baseline browsers for at least 2.5 years." The Baseline browsers are Safari on iOS and macOS, Chrome on Android and desktop, Edge on desktop, and Firefox on Android and desktop.
Run that clock on the Popover API and you get a useful answer. Support landed in January 2025, so on the 2.5 year rule it will not be classified as widely available until partway through 2027. Newly available is real support, not a promise, but it tells you that visitors on older devices may still miss out. We explain how we use these tiers in practice in our piece on Baseline web features.
Three HTML attributes, no script. You add the popover attribute to the element you want to show. You add popovertarget to a button, pointing at that element's id. The browser wires up the toggle, the escape key, and the outside click for you. A third attribute, popovertargetaction, lets you force show or hide instead of toggle.
The minimal version is two lines. A button with popovertarget pointing at an id, and a div with the popover attribute and that id. That is a working, keyboard-accessible, dismissible popover. No library, no event listeners, no state variable tracking whether it is open.
The popover attribute takes a state value that controls dismissal behaviour. The auto state closes when you click outside or press escape, and closes other auto popovers when it opens. The manual state stays open until something explicitly closes it, which is what you want for a toast notification. There is also a hint state for tooltip-style behaviour that should not close a menu already on screen.
The other piece of the machinery is the top layer. MDN describes showPopover() as showing "a popover element by adding it to the top layer." That is the browser's own stacking context above everything else on the page, and it is the reason a native popover never gets trapped behind a header with a z-index of 9999. Every developer who has fought that bug will appreciate what this removes.
Use popover when the page behind should stay usable. Use dialog when it should not. That single question answers it almost every time. Popovers are non-modal by definition, so a menu, a tooltip, or a toast is a popover. A confirmation the user must answer before continuing is a dialog.
The dialog element is the older and more settled of the two. MDN reports it has "been available across browsers since March 2022", which puts it comfortably in the widely available tier. If you need a modal today and support for older devices matters, dialog is the safer pick by a wide margin.
Dialog also gives you two distinct modes. As MDN puts it, "modal dialog boxes block interaction with other UI elements, making the rest of the page inert, while non-modal dialog boxes allow interaction with the rest of the page." The showModal() method gives you the blocking version, and show() gives you the non-blocking one. Only showModal() gets you the ::backdrop pseudo-element, which MDN notes "could be used, for example, to blur, darken, or otherwise obfuscate the inert content behind the modal dialog."
Our rule on client projects is simple. Modal goes to dialog with showModal(). Everything that hovers, drops down, or slides in without blocking goes to popover. We do not mix the two on one element, because that is where the accessibility problems start.
For most sites, yes. Tippy.js, Floating UI, and the overlay layers inside Radix UI and Headless UI exist because the platform had no answer. The platform now has one for showing and hiding. What those libraries still do better is positioning, which the Popover API deliberately leaves alone.
That split is the useful way to think about it. Showing, hiding, dismissing, stacking, and keyboard handling are now free and native. Working out where on screen the popover should sit relative to its trigger is a separate problem the browser does not solve with these three attributes.
The payoff is real, though. Dropping a positioning-only dependency in place of a full overlay library removes JavaScript from the critical path, and less shipped JavaScript is one of the most reliable performance wins available. Every kilobyte you do not send is a kilobyte the browser does not have to download, parse, and execute before the page becomes usable.
It gives you a much better starting point, not a finished result. The browser handles the escape key, dismissal, and top layer placement, which are the three things hand-rolled implementations most often break. You still own the labelling, the focus order, and making sure the trigger describes what it opens.
The dialog element's documentation shows how much the browser can take off your plate when it knows the semantics. MDN notes that keyboard users expect Escape to close a modal, that only the most recently shown dialog should close, and that "when using dialog, this behavior is provided by the browser." Native elements come with the conventions already wired in.
What you still have to do is give the content meaning. A popover full of unlabelled icon buttons is inaccessible whether the browser opened it or your JavaScript did. Screen reader users need the trigger to say what it does and the contents to have real names. Our WCAG accessibility guide covers the labelling patterns we use.
One habit worth borrowing from the dialog docs applies here too. MDN advises adding autofocus to "the element the user is expected to interact with immediately" rather than leaving initial focus to chance. Being deliberate about where focus lands is most of accessible overlay work.
Not with the Popover API. It puts the element in the top layer and leaves placement to CSS. For anything beyond centring it on screen, you need either your own positioning CSS or the separate CSS anchor positioning module, which MDN describes as defining "features that allow you to tether elements together."
Anchor positioning is the piece that would complete the picture. It lets you bind a popover to its trigger, define fallback positions when the default would overflow the viewport, and hide the element when tethering no longer makes sense. That is exactly the job Floating UI does in JavaScript today.
Before you rely on it, check its current Baseline status yourself rather than trusting any article, including this one. Support for CSS modules moves month to month, and the honest answer for anchor positioning is that you should look it up on MDN on the day you plan to ship. That is the discipline we apply to every newer CSS feature.
We do, with a fallback. The Popover API degrades reasonably: in a browser that does not understand the attributes, the element renders as ordinary content rather than disappearing. That means a small amount of CSS and a feature check gives you a safe path for the minority of visitors on older browsers.
This is standard progressive enhancement, and it is the reason newly available features are usable well before they hit the widely available tier. You build the version that works everywhere, then let capable browsers take the better path. The people on old devices get a plainer experience instead of a broken one.
Where we would still hesitate is a checkout flow or anything where a failed interaction costs real money. For a navigation menu, a tooltip, or a notification toast, the risk is close to zero and the code savings are immediate. For a payment step, we use the boring option and revisit in a year.
Look at what your site currently loads to power its menus and tooltips. If there is a dedicated overlay library in the bundle, check whether the Popover API and a little CSS could replace it. Most marketing sites we audit are shipping several kilobytes of JavaScript for behaviour the browser now provides free.
Then be honest about which overlays are truly modal. The most common mistake we find is a modal built out of divs that traps nothing and blocks nothing, sitting where a dialog element with showModal() would have done the job correctly with less code.
If you want help working out which parts of your front end the platform has quietly made unnecessary, we are happy to walk through it. That audit is usually one of the fastest performance wins on an older build. Reach out through phoenix.studio and tell us what you are running.
Tell us where you want to go. We'll tell you how we'd get you there.