Check out our latest updates including dark mode support.
Toast
A [popover] promoted to the top layer, so it always
renders above everything else on the page, no
z-index needed. Open and close it declaratively with
popovertarget, no JavaScript involved. Put an
Alert inside for the actual
message.
Default
Add the toast class to a [popover]
element and trigger it with a popovertarget button.
Left as the default "auto" popover mode, it
light-dismisses on outside click or Escape, same as any other
popover.
<button popovertarget="my-toast">Show toast</button>
<div id="my-toast" popover class="toast">
<article role="status">
<svg><!-- icon --></svg>
<strong>New features available</strong>
<p>Check out our latest updates including dark mode support.</p>
</article>
</div>
Placement
Use data-placement the same way as
Popover: a
"<side> <side>" tuple like
"bottom right". Bare "top",
"bottom", "left", or
"right" center the toast along that edge, and
"center" centers it in the viewport. It defaults to
"bottom right" when omitted.
Anchored to the top left corner.
Centered along the top edge.
Centered along the bottom edge.
The default placement.
<div popover class="toast" data-placement="top left">...</div>
<div popover class="toast" data-placement="top">...</div>
<div popover class="toast" data-placement="bottom">...</div>
<div popover class="toast" data-placement="bottom right">...</div>
Multiple
Use popover="manual" instead of the bare
popover (which defaults to "auto") so
opening one toast doesn't close another. Toasts sharing the same
data-placement automatically fan out behind each
other as more of them open, up to 6 deep, purely with CSS
:has() counting how many later same-placement toasts
are currently open, no manual offsets and no JavaScript.
This only works between toasts that are DOM siblings (unrelated
content is fine in between, they don't need to be adjacent), since
CSS has no way to compare document position across different
parents. In practice that means keeping toasts together under one
shared container, commonly placed once near the end of
<body>, the same way most toast libraries work.
Fans out behind newer toasts automatically.
Fans out behind newer toasts automatically.
Fans out behind newer toasts automatically.
Fans out behind newer toasts automatically.
Fans out behind newer toasts automatically.
<button popovertarget="toast-1">Show toast 1</button>
<button popovertarget="toast-2">Show toast 2</button>
<!-- ...up to as many toasts as you need, up to 6 deep -->
<div id="toast-stack">
<div
id="toast-1"
popover="manual"
class="toast"
data-placement="bottom right"
>
<article role="status">
<svg><!-- icon --></svg>
<strong>Toast 1</strong>
<p>Fans out behind newer toasts automatically.</p>
<button
class="ghost square round"
aria-label="Remove"
popovertarget="toast-1"
popovertargetaction="hide"
>
<svg><!-- x icon --></svg>
</button>
</article>
</div>
<div
id="toast-2"
popover="manual"
class="toast"
data-placement="bottom right"
>
...
</div>
</div>
Dismissible
Pair a ghost square round button with
popovertarget and
popovertargetaction="hide" to close it, fully
declarative.
<div id="my-toast" popover="manual" class="toast" data-placement="bottom">
<article role="status" class="constructive">
<svg><!-- icon --></svg>
<strong>Profile updated successfully</strong>
<button
class="ghost square round"
aria-label="Remove"
popovertarget="my-toast"
popovertargetaction="hide"
>
<svg><!-- x icon --></svg>
</button>
</article>
</div>