Native HTML Series Part 3: Tooltips and Menus with the Popover API
Welcome to Part 3 of our series on replacing third-party UI libraries with native HTML. We’ve already covered zero-JS accordions and native modals. Today, we are looking at the newest tool in the browser's arsenal: the Popover API.
Think about how often you build tooltips, user profile dropdowns, or custom toast notifications. Historically, getting these to float above your content without z-index bugs—while also remembering to close them when the user clicks somewhere else—required a dedicated JavaScript library or writing complex event listeners.
The new popover attribute solves all of this natively.
The Bare Bones
Unlike <dialog>, which is a specific HTML tag, popover is a global attribute. You can attach it to a <div>, an <article>, or any other element to instantly turn it into a floating popup.
Here is the entire HTML required to create a working popover menu, with absolutely zero JavaScript:
<button popovertarget="user-menu">Open User Menu</button>
<div id="user-menu" popover>
<ul>
<li><a href="#">Profile</a></li>
<li><a href="#">Settings</a></li>
<li><a href="#">Sign Out</a></li>
</ul>
</div>
That's it. By linking the button's popovertarget to the id of the div, the browser handles the click events completely behind the scenes.
The Magic: Built-In Light Dismiss
In Part 2, we had to write a JavaScript function to close our modal when the user clicked the background.
With the Popover API, this behavior (known as "light dismiss") is built-in by default. When a popover is open, doing any of the following will automatically close it:
- Clicking anywhere outside the popover.
- Pressing the
Escapekey. - Opening another popover.
Furthermore, just like the <dialog> element, popovers are promoted to the browser's "Top Layer," guaranteeing they will always sit on top of your other content, regardless of the parent container's overflow: hidden or z-index rules.
The CSS Glow-Up
By default, an open popover is just centered in the middle of the screen. We can use CSS to style it as a sleek, floating menu and add transitions using the :popover-open pseudo-class.
/* Style the popover box */
[popover] {
padding: 1rem;
border: 1px solid #e2e8f0;
border-radius: 8px;
box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1);
background: white;
/* Basic positioning - reset defaults */
margin: auto;
max-width: 250px;
}
/* Remove default list styling for our menu */
[popover] ul {
list-style: none;
padding: 0;
margin: 0;
}
[popover] li {
padding: 0.5rem 0;
border-bottom: 1px solid #f1f5f9;
}
[popover] li:last-child {
border-bottom: none;
}
Note: For true relative positioning (e.g., anchoring the popover exactly below the button), you would use the new CSS Anchor Positioning API, which pairs perfectly with popovers but is a topic for a future post!
Why This Matters
The Popover API is a massive win for developer experience. It standardizes one of the most common UI patterns on the web. It means less JavaScript sent to the client, fewer accessibility bugs, and a much cleaner DOM. If you are writing end-to-end tests with tools like Playwright, testing these interactions becomes a breeze because the browser's native state is completely predictable.
Interactive Demo:
(Click the button below to see the popover in action. Notice how clicking anywhere else on the screen instantly closes it—no JS required!)
Top comments (0)