# The Popover API

> Build native browser popovers with the Popover API using HTML attributes, auto and manual modes, CSS backdrop styling, and JavaScript show and hide methods.

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2026-08-19 | Updated: 2026-08-03 | Topics: [Web Platform](https://flaviocopes.com/tags/platform/) | Canonical: https://flaviocopes.com/popover-api/

The **Popover API** gives you native popovers in the browser. You do not need to manage the top layer or light dismiss yourself.

Add the `popover` attribute to an element and it becomes a popover. The browser handles layering, keyboard navigation order, the relationship with the invoker, and light dismiss for auto popovers.

A popover is not modal. It does not make the rest of the page inert or trap focus like `<dialog>.showModal()`.

## HTML only, no JavaScript

The simplest setup uses a button with `popovertarget`.

```html
<button popovertarget="help-tip">Show help</button>

<div id="help-tip" popover>
  <p>Click save to store your changes.</p>
</div>
```

Click the button and the popover opens. Click outside and it closes. That outside click behavior is called **light dismiss**.

You can point `popovertarget` at any element with a `popover` attribute. No [event listeners](https://flaviocopes.com/javascript-events/) required.

## Auto vs manual popovers

**Auto popovers** use `popover="auto"` or just `popover`. Light dismiss works. Opening one normally closes another open auto popover. Nested auto popovers are the exception, so menus can contain submenus.

**Manual popovers** use `popover="manual"`. They stay open until you close them with code or another toggle. Light dismiss does not apply.

```html
<button popovertarget="status-panel">Toggle status</button>
<div id="status-panel" popover="manual">
  <p>Deploy in progress...</p>
</div>
```

Use manual mode for panels that should survive clicks elsewhere on the page, like a status widget or a persistent notification.

## Styling with ::backdrop and :popover-open

Popovers sit in the **top layer**, above normal page content. Style the open state with `:popover-open`.

```css
[popover] {
  border: 1px solid #ccc;
  padding: 1rem;
  border-radius: 8px;
}

[popover]:popover-open {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
}

[popover]::backdrop {
  background: rgba(0, 0, 0, 0.4);
}
```

The `::backdrop` pseudo-element covers the page behind the popover. Dim it, blur it, or leave it transparent.

## JavaScript API

You can open and close popovers from code with three methods.

```js
const tip = document.querySelector('#help-tip')

tip.showPopover()
tip.hidePopover()
tip.togglePopover()
```

Listen for state changes with [events](https://flaviocopes.com/javascript-events/).

```js
tip.addEventListener('toggle', (event) => {
  console.log(event.newState) // 'open' or 'closed'
})
```

Use the JS API when the trigger is not a button, or when you open the popover from app logic.

## When to use it

Reach for the Popover API for tooltips, menus, and small panels. It is lighter than building a modal from scratch.

For full-screen dialogs with complex focus rules, a `<dialog>` element might still fit better. Popovers shine on small, contextual UI.

All modern browsers support the Popover API today. You can use it without a polyfill on current Chrome, Safari, Edge, and Firefox.
