<dialog>

Native HTML Dialog — Live Demos

4 examples · zero libraries

Basic Modal with showModal()

The simplest usage. The browser handles top-layer rendering, focus trapping, and Escape-to-close automatically. returnValue is set by form method="dialog".

✓ Focus trapped ✓ Escape closes ✓ No z-index
Last closed with:
--:--:--Waiting — click Open Modal to begin

What the browser gives you for free

Open the modal and try these — no JavaScript needed for any of them:

Tab key
Cycles only through buttons inside the dialog
Escape key
Fires cancel event, then closes dialog
Top layer
Renders above all z-index stacking contexts
Focus return
On close, focus goes back to trigger button

Animated Modal — @starting-style + allow-discrete

CSS-only entry and exit animation using @starting-style and transition-behavior: allow-discrete. Both the dialog and the frosted-glass backdrop animate smoothly.

Frosted backdrop Scale + fade
--:--:--Waiting — click Open Animated

The key CSS technique

The trick to animating dialog exit is allow-discrete — it lets the transition run even as the element leaves the top layer.

dialog { opacity: 1; transform: scale(1); transition: opacity .28s ease, transform .28s ease, display .28s allow-discrete, /* exit anim */ overlay .28s allow-discrete; /* top-layer exit */ } /* State when dialog is CLOSED (exit target) */ dialog:not([open]) { opacity: 0; transform: scale(.94); } /* State at START of open animation (enter from) */ @starting-style { dialog[open] { opacity: 0; transform: scale(.94); } }

Side Drawer — Same Element, Different CSS

Override position: fixed; inset: 0 auto 0 0 to pin the dialog to the left edge. Full focus trapping and Escape key still work — no extra JavaScript needed.

Slide animation ✓ Backdrop click closes
--:--:--Waiting — click Open Drawer

The CSS override

Just three property changes convert any centered modal into a side drawer:

dialog.drawer { /* Pin to left edge */ position: fixed; inset: 0 auto 0 0; /* top right bottom left */ margin: 0; /* Full height */ height: 100dvh; max-height: 100dvh; border-radius: 0 16px 16px 0; max-width: none; /* Slide in from left */ transform: translateX(-100%); transition: transform .3s cubic-bezier(.4,0,.2,1), display .3s allow-discrete, overlay .3s allow-discrete; } dialog.drawer[open] { transform: translateX(0); }

form method="dialog" — Built-in Return Values

When a <form method="dialog"> submits, the dialog closes and dialog.returnValue is set to the clicked button's value. No JavaScript needed to close.

form method="dialog" ✓ returnValue on close
--:--:--Waiting — click Edit Profile

No JavaScript to close — the form does it

<dialog id="editDialog"> <form method="dialog" id="editForm"> <input name="name" type="text"> <input name="email" type="email"> <!-- value becomes dialog.returnValue --> <button type="submit" value="cancel">Cancel</button> <button type="submit" value="save">Save</button> </form> </dialog> // Read the result after close dialog.addEventListener('close', () => { if (dialog.returnValue === 'save') { const data = Object.fromEntries(new FormData(form)); saveProfile(data); } });

Confirm Delete

This will permanently delete your project and all associated files.

⚠ This action cannot be undone.

Invite Team Member

Share access to this workspace with your teammates.

💡 Watch the frosted glass backdrop and scale + fade animation on open and close
W
w3tweaks

Edit Profile