popover
⚡ TL;DR
easy way to make any element toggle its display with just an attribute on both the trigger and the triggered
- easy to customize via JS but not needed
- good defaults
🧪 Experiment
in its simplest form
At its simplest popover needs:- the element you want to use as popover (it can be whatever tag, e.g. a div), with an "id" AND a `popover` attribute
- a button with a `popovertarget` attribute passing the popover "id" value
This is the simplest popover
<button popovertarget='my-popover-target'>Open Popover</button>
<div id='my-popover-target' popover>
<p>This is the simplest popover</p>
</div>
Deeper test still no JS: add specific actions
You can add a close button inside the popover just using HTML, no JS, using
the `popovertargetaction` and the `hide` value. For it to work you also need
to add a popovertarget attribute. We're slowly getting the idea behind, the
common mechanisms.
You could also add this button outside the popover BUT
it would be useless since anyway clicking outside the popover closes it.
This is the simplest popover
<button popovertarget="my-popover-test-2" popovertargetaction="hide">
<span aria-hidden="true">💣</span>
<span class="sr-only">Close</span>
</button>
Weird edge cases
Sibling popovers opened at the same time
What happens if I am trying to open a popover while another one is opened? It closes the previous one and open the new one.This is the first popover opened, now open the second one
The first popover closed when trying to open this one
Nested popovers
This is the first popover opened, now open the second one inside here
The first popover remains opened while this one got opened too
🛠️ Disable auto mode and switch to manual
By default the "popover" attribute in the popover element implicitly means value is "auto". You can change this by explicitly adding `popover="manual"` The changes are:- it disables the light dismiss (close popover when click outside the popover or hit Escape
- It also DO NOT auto close any other popover opened
- You then need to add other ways to close it: close button (using the `popovertargetaction="hide"` and/or a timer).
Toast 1
🎨 Styling
Specific styling possibilities: `::backdrop`
This is a styled popover
#my-popover-target-5::backdrop {
background-color: color-mix(in oklab, aquamarine, transparent 20%);
backdrop-filter: blur(2px);
&:popover-open {
@starting-style {
opacity: 0;
color: green;
filter: blur(0);
transform: translateY(20px) scale(0.9);
}
opacity: 1;
color: red;
filter: blur(0);
transform: translateY(0) scale(1);
}
transition: transform 0.5s, opacity 0.5s, display 0.5s, color 0.5s;
}
Using JS: show / hide / toggle
document
.getElementById("show-popover-btn")
.addEventListener("click", () =>
document.getElementById("popover-6").showPopover()
);
document
.getElementById("hide-popover-btn")
.addEventListener("click", () =>
document.getElementById("popover-6").hidePopover()
);
document
.getElementById("toggle-popover-btn")
.addEventListener("click", () =>
document.getElementById("popover-6").togglePopover()
);
Differences with existing solutions
We can easily imagine its benefits for features such as mobile nav modal, toasts, ... But why using them over other existing solutions? One reason is: the popover can be ANY element, when the dialog is a special tag. This is already a big advantage over the dialog element when in use in a Design Systsem for example. Think about the Topbar. You can have an element with the menu links as a normal div. And when you click on the hamburger menu it transofrms it into a full blown full-screen nav modal. For toast it makes lot of sense too, although we would then need to add JS for the timer, so the beenfits are limited.
Key differences with the dialog element
- it does NOT provide semantic of its own. It does not convey any meaning per se. Which is good (flexibility for its use), but also remove the A11y benefit of the dialog element which convey this specific meaning.
- dialog block background scrolling and interactions,not popover (if mode manual, else light-dismiss means it will close the popover)
- popover supports light dismiss (on mode auto), dialog does not
- very easy to create a no-JS popover, when the no-JS dialog is basically pointless
Possible use cases
- toasts (in mode manual adding timer function)
- tooltips (combining it with the future `anchor` HTML attribute
- menu
- modals / popups (but no `inert` built-in functionality, no focus moved nor trapped)
Benefits of Popover
- easy way to display hide a modal with no JS
- easy styling of a modal (:backdrop, :popover-open, @starting-styles)
- No semantic
- light dismiss (by default but can be disabled)
- close currently opened popovers (by default but can be disabled)
- easy to use & customize
Drawbacks/footgun of Popover
- No `inert` (diff with dialog)
- No progressive enhancement. If not supported then the popover is displayed all the time by default, it looks broken
- Focus is not automatically moved nor trapped inside the popover (diff with dialog)
- No semantic
🤔 Opinion
- very easy to use in its simplest form
- possible to use with no JS
- fairly close usecase with details, dialog, and soon selectmenu. It gives more tools.