Short answer: Use the dialog element and open it with showModal() when people must finish something before going back to the page. The browser then makes the rest of the page inert, puts the focus inside and lets Escape close it. Give it a name and a visible close button, and send the focus back where it was.
Modal or non-modal
MDN describes the dialog element as a modal or non-modal dialog box. A modal one blocks the rest of the page and makes it inert. A non-modal one lets people keep using the page around it.
| How you open it | The rest of the page | Escape |
|---|---|---|
| showModal() | Inert, behind a backdrop | Closes it |
| show() | Still usable | Doesn’t close it |
| The open attribute | Still usable | Doesn’t close it |
| A div with role="dialog" | Whatever your script does | Only if your script handles it |
From MDN and web.dev, read November 5, 2026.
web.dev adds that a modal dialog sits on top of the page, and a semi-transparent backdrop covers the rest by default. You can style that backdrop with the ::backdrop pseudo-element. MDN advises against opening a dialog with the open attribute: it is always non-modal that way.
The focus goes in, and comes back
When showModal() opens a dialog, the focus moves to the first element inside it that can take it. MDN recommends the autofocus attribute on the control people need first, or on the close button when nothing else comes first.
While a modal dialog is open, web.dev notes that pressing Tab again and again only reaches what is inside it. When the dialog closes, the focus returns to the element that opened it. Our keyboard navigation guide shows how people move through a page without a mouse.
How people close it
Escape closes a dialog opened with showModal(), and MDN asks you to keep it that way, since keyboard users expect it. Escape doesn’t close a non-modal dialog, so its own close button matters even more.
web.dev says to treat a visible close button as required, even though the specification doesn’t ask for one. MDN’s closedby attribute decides the rest: with the value any, a click or tap outside also closes the dialog, which MDN calls light dismiss.
A name and the right role
Browsers expose the dialog element much like a custom one built with role="dialog". MDN notes that a dialog opened with showModal() gets aria-modal="true" on its own.
Give the dialog a name, usually by pointing aria-labelledby at its heading, as the W3C pattern for modal dialogs describes. Our aria-label guide covers when to name an element with visible text.
If you build it without the dialog element
MDN warns that the dialog element brings features you must rebuild if you use a div instead. aria-modal="true" alone tells assistive technology the dialog is modal, but doesn’t make it modal.
You keep the focus inside with a script, close it with Escape and mark everything else inert. The inert attribute does the last part: inert content can’t be clicked or focused, and it leaves the accessibility tree. A dialog that isn’t modal should drop aria-modal or set it to false. Our what is ARIA guide explains why ARIA leaves the behavior to your script.
How to build an accessible modal
- Use the dialog element and open it with showModal().
- Name it by pointing aria-labelledby at its heading.
- Put a visible close button inside it.
- Keep Escape working, and decide whether a click outside closes it too.
- Add autofocus to the control people need first.
- Return the focus to the button that opened it when it closes.
- Check with the keyboard and a screen reader that nothing behind it can be reached.
Our cookie notice as a dialog
On November 5, 2026, we read our cookie notice as a dialog in Chrome’s accessibility tree, on the home page and a guide, in both languages. It is a div with role="dialog", named by its title, “Your privacy choices”. The compact notice is non-modal: it takes no focus and the page stays usable.
The preferences, opened from the footer link, are modal. The focus moves to the first control inside, and twelve presses of Tab never left them. Escape closes them and sends the focus back to the footer link.
That morning the page behind still answered: on a guide, a click on our logo left the page, and Chrome kept the page in its tree. Now the page behind is inert while the preferences are open, and a click outside closes them like Escape.
Before you publish
- The dialog has a name that matches its heading.
- The focus moves inside when it opens.
- Tab and Shift+Tab stay inside a modal dialog.
- Escape and a visible button both close it.
- The focus returns to the control that opened it.
- Nothing behind a modal dialog can be clicked or read.
RememberA modal dialog is a promise: only what is inside works until it closes. showModal() keeps that promise for you; with a div, your script has to.
Our web design service builds dialogs that keep this promise.
Quick answers about the dialog element
What is the difference between show() and showModal()?
showModal() opens the dialog as a modal: the rest of the page becomes inert, a backdrop covers it and Escape closes it. show() opens it as non-modal, so people can still use the page, and Escape doesn’t close it, as web.dev explains.
Does a dialog need a close button?
Treat it as required. web.dev notes that the specification doesn’t ask for one, but a visible button that gets focus helps everyone. MDN calls an explicit close, cancel or confirm button the most reliable way to let all users close a dialog.
Is aria-modal enough to make a dialog modal?
No. MDN says aria-modal="true" tells assistive technology that a dialog is modal but doesn’t make it so. You still keep the focus inside, close it with Escape and make the rest of the page inert, which showModal() does for you.
Where should the focus go when a dialog opens and closes?
Into the dialog when it opens: showModal() puts it on the first element that can take it, and autofocus can pick another. When the dialog closes, web.dev says the focus returns to the element that opened it.
Can a dialog close when people click outside it?
Yes, if you choose so. MDN describes the closedby attribute: with closedby="any", a click or tap outside closes the dialog, like Escape. A modal dialog opened with showModal() doesn’t close that way unless you set it.
Sources
Read on November 5, 2026. MDN Web Docs: <dialog> HTML dialog element, ARIA: aria-modal attribute and inert HTML global attribute. web.dev: Dialog. W3C Web Accessibility Initiative: Dialog (Modal) Pattern. Our case: our own pages, read in a browser on November 5, 2026.
