The <dialog> Element Probably Replaces Your Modal Library
Modal libraries exist because building a correct modal by hand is genuinely hard: trap focus, restore focus on close, handle Escape, block the page behind, win the z-index war. The dialog element ships all of that in the browser, and it's been in every engine since 2022.
<dialog id="confirm">
<h2>Delete this post?</h2>
<p>This can't be undone.</p>
<form method="dialog">
<button value="cancel">Cancel</button>
<button value="delete">Delete</button>
</form>
</dialog>
const dialog = document.getElementById('confirm');
dialog.showModal();
dialog.addEventListener('close', () => {
if (dialog.returnValue === 'delete') actuallyDelete();
});
The parts people miss
form method="dialog" is the hidden gem inside the hidden gem: submitting that form closes the dialog and sets dialog.returnValue to the clicked button's value. A complete confirm-flow with no click handlers on the buttons at all.
The top layer. showModal() promotes the dialog above everything, regardless of z-index or parent overflow. That chat widget with z-index 2147483647? The dialog renders above it. This alone has ended hours of stacking-context archaeology for me.
::backdrop is a real, styleable pseudo-element:
dialog::backdrop {
background: rgb(2 6 23 / 0.6);
backdrop-filter: blur(2px);
}
Escape works out of the box, firing a cancel event you can intercept if there are unsaved changes.
Light dismiss (click outside to close)
The one behavior not built in yet everywhere. The trick: clicks on the backdrop target the dialog element itself, clicks inside target children:
dialog.addEventListener('click', (e) => {
if (e.target === dialog) dialog.close();
});
Give the dialog's inner content a wrapper with padding: 0 on the dialog itself, or the padding area counts as "the dialog" and closes unexpectedly.
Two honest caveats
- show() (non-modal) doesn't trap focus or add a backdrop - most of the time you want showModal().
- Animating open/close needs the newer allow-discrete / @starting-style CSS, which is Chromium and recent Safari/Firefox; older browsers just skip the animation, which is a fine fallback.
Between dialog for modals and accent-color for form controls, a surprising amount of "UI library" territory is now just the platform.
Full-stack web developer sharing practical tutorials and building tools that ship.
Got something on your mind?
My inbox is open - no forms disappearing into the void here.
- Just say hello Found a tutorial useful? Spotted a mistake? Tell me.
- Hire me for a project Have something custom in mind? Let's talk scope and timelines.
- Product support Bought something here? I'll help you get it running.
I usually reply within 1-2 business days.