Modal dialogs without a JavaScript library
The old way was a custom overlay plus JavaScript for open/close, ESC key, click-outside, focus trap, and z-index. The dialog element and showModal() handle all of that.
2 position: fixed;
3 inset: 0;
4 background: rgb(0 0 0 / .5);
5}
6
7/* JS: addEventListener click, keydown ESC, focus trap,
8 aria-hidden, body scroll lock, z-index stacking */
2 padding: 1rem;
3}
4
5dialog::backdrop {
6 background: rgb(0 0 0 / .5);
7}
8/* JS: dialog.showModal(); dialog.close(); */
Built-in behavior
ESC to close, click outside to close, and focus trapping come free. No extra JS.
Accessible by default
The browser manages focus and return focus. Top layer stacking is handled for you.
One element
No overlay div, no z-index wars. Style dialog and ::backdrop and you are done.
How it works
The old approach meant a fixed overlay div, JavaScript to open and close it, keydown listeners for Escape, click-outside detection, focus trapping so tab stays inside the modal, and careful z-index management. Easy to get wrong or forget a detail.
The modern approach is a single <dialog> element. Call dialog.showModal() to open it: the browser puts it in the top layer, traps focus, and provides ESC and click-outside behavior. Style the ::backdrop pseudo-element for the dimmed background. No overlay div, no focus library.