Drawer
A panel that slides in from the edge — same native <dialog> as the modal, just anchored to the side and sliding instead of scaling. Focus trap, Esc and light dismiss come free.
dialogexit animations
How it works
It’s the Dialog with two changes: pin it to an edge, and slide instead of
scale. Everything else (top layer, focus trap, inert background, Esc, declarative open) is
identical, because it’s the same native <dialog>.
my-0 mr-0 ml-autooverrides Tailwind’s zeroed dialog margins to push the panel flush against the right edge;h-dvh max-h-dvhmakes it full height. Swap toml-0 mr-autofor a left drawer, ormt-auto mb-0 w-fullfor a bottom sheet.- The slide: the panel sits at
translate-x-full(off-screen right) by default,open:translate-x-0brings it in, andstarting:open:translate-x-fullsets the entry frame.transition-all transition-discrete(transition-behavior: allow-discrete) keepsdisplay/overlayalive so the panel slides out too, instead of vanishing. commandfor+command="show-modal"opens it declaratively;closedby="any"gives you backdrop-click dismiss. The header’s close button is justcommand="close".- Inside, a
flex flex-colwith a fixed header and footer and aflex-1 overflow-y-autobody. Long content scrolls while the footer stays put. - The panel and that scrollable body both get
overscroll-none, and the backdrop getsbackdrop:overflow-hidden backdrop:overscroll-contain, so scrolling the cart to its end neither drags the page behind it nor rubber-bands the list. Needs Chrome 144+; elsewhere the background scrolls, nothing breaks.
Accessibility
Same as Dialog: focus moves into the drawer and is trapped, the page behind goes inert, Esc
closes it, and focus returns to the trigger on close. Like the dialog, the panel
needs an accessible name: the demo points aria-labelledby at the heading, so it announces
as “Your cart”.
Reduced motion
The global prefers-reduced-motion rule in the token paste collapses the slide to an instant
show/hide. The drawer still opens and closes, it just doesn’t travel.
Browser support
Minimum stable version per engine, resolved at build time from MDN's browser-compat-data; Baseline status from the official web-features dataset. Everything degrades gracefully — the “when missing” column is the actual behavior, not a broken page.
| Feature | Chrome | Edge | Firefox | Safari | When missing |
|---|---|---|---|---|---|
| <dialog> elementBaseline · widely available | 37 | 79 | 98 | 15.4 | Baseline, widely available. Modal behavior, focus handling and Esc-to-close are native. |
| Invoker commands (commandfor / command)‡Baseline 2025 · newly available | 135 | 135 | 144 | 26.2 | Buttons with commandfor do nothing. Until Baseline reaches your audience, open the dialog with a 3-line shim or from your framework. |
| closedby="any" (light dismiss)‡Limited availability | 134 | 134 | 141 | ✕ | Esc still closes the dialog (platform default); clicking the backdrop does not. |
| Entry/exit animations (allow-discrete + @starting-style)†Baseline 2024 · newly available | 117 | 117 | 129 | 17.5 | Elements appear and disappear instantly. Nothing breaks — you just lose the animation. |
† @supports cannot test at-rules, so the badge checks transition-behavior: allow-discrete, which co-shipped with @starting-style in every engine.
‡ HTML feature — @supports can only test CSS, and we ship no JS to detect it, so it gets no live badge.