The page behind stays usable.
A panel that slides in from the edge of the screen instead of
appearing centered. Add the drawer class to a
Dialog, or to a
Popover when it
shouldn't block the page.
Composed of
Dialog- The modal it is built on
Popover- The non-modal version, without a backdrop
Card- The surface inside the drawer
Works with
Button- Actions, like apply or close
Standalone
<link rel="stylesheet" href="https://esm.sh/@erikt/ui/drawer.css" />
Default
Add the drawer class to a <dialog>. By
default it slides in from the right. Everything else, including
.showModal(), closedby, and
scroll-lock, works exactly like a regular dialog.
The Drawer doesn't have a background color, so place an Card as the first child.
<button onclick="document.getElementById('my-drawer').showModal()">
Open drawer
</button>
<dialog id="my-drawer" class="drawer" closedby="any">
<article class="card">
<p style="margin-bottom: 1rem">This is a drawer.</p>
<form method="dialog">
<button class="outlined">Close</button>
</form>
</article>
</dialog>
Position
Use data-position to slide the drawer in from
left, right, top, or
bottom. It defaults to right when omitted.
<dialog class="drawer" data-position="left">...</dialog>
<dialog class="drawer" data-position="right">...</dialog>
<dialog class="drawer" data-position="top">...</dialog>
<dialog class="drawer" data-position="bottom">...</dialog>
As a popover
Put the drawer class on a popover element
to open it without a backdrop. The rest of the page stays usable
while it's open. Open it with popovertarget, no
JavaScript needed. Clicking outside or pressing
Esc closes it, and data-position works the
same way.
<button popovertarget="my-drawer">Open drawer</button>
<div id="my-drawer" class="drawer" popover>
<article class="card">
<header>
<strong>Notifications</strong>
</header>
<p>The page behind stays usable.</p>
<footer>
<button
class="outlined"
popovertarget="my-drawer"
popovertargetaction="hide"
>
Close
</button>
</footer>
</article>
</div>
With header & footer
Use the card's <header> and
<footer> to pin controls to the top and bottom of
the drawer, same as inside a regular dialog.
<dialog class="drawer" closedby="any">
<article class="card">
<header>
<strong>Filters</strong>
</header>
<p>Drawer content goes here.</p>
<footer>
<form method="dialog">
<button>Apply</button>
<button class="outlined">Cancel</button>
</form>
</footer>
</article>
</dialog>
API reference
| Type | Classes / attributes | What it does |
|---|---|---|
| Placement | [data-position="left"][data-position="right"][data-position="top"][data-position="bottom"] |
The edge the drawer slides in from. Right by default |
| Variant | dialog.drawer[popover].drawer |
A dialog opens with a backdrop. A popover opens without one and leaves the page usable |
| Scroll lock | [scroll-lock] |
Stops the page from scrolling while a dialog drawer is open |