The quiet power of the <dialog> element

Sam Lindqvist

·

·

6 min read

For years, building a modal meant reaching for a library or writing two hundred lines of focus-trapping code. Today the browser does almost all of it for you, and most teams still have not noticed.

What you get for free

Calling showModal() on a <dialog> element gives you a surprising amount of behaviour out of the box:

  • The rest of the page becomes inert, so focus and screen readers stay inside.
  • Esc closes it, and focus returns to the element that opened it.
  • It renders in the top layer, so z-index battles are over.
  • A ::backdrop pseudo-element you can style however you like.
const dialog = document.querySelector('dialog');
openButton.addEventListener('click', () => dialog.showModal());
dialog.addEventListener('close', () => console.log(dialog.returnValue));

The parts you still own

The element is not magic. You still need a visible heading, a clear way to close it, and sensible initial focus. Closing on a backdrop click is not built in either, though it takes three lines to add.

Reach for the platform first. Add code only for the gap between what HTML does and what your users need.

The command palette on this site (press Ctrl K) is a plain <dialog> with a search field and a list. It is about eighty lines of JavaScript, and most of those are for filtering.