Layout Intermediate

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.

Old 15+ lines
1.overlay {
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 */
Modern
6 lines
1dialog {
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.

Browser Support
96%
Chrome Firefox Safari Edge
Lines Saved
15+ → 6
No overlay or focus-trap JS
Old Approach
Custom overlay + JS
ESC, click-outside, focus trap, z-index
Modern Approach
dialog + showModal()
::backdrop, top layer

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.

ESC