The HTML dialog tag

By

Learn the native HTML dialog element for accessible modals: showModal, close, form method dialog, backdrop styling, and why it beats div modals.

~~~

The HTML dialog tag gives you a native modal without building one from a div.

For years we stacked position: fixed divs and wired up focus trapping by hand. The dialog element handles most of that for you.

Basic markup

<dialog id="settings">
  <h2>Settings</h2>
  <p>Choose your preferences.</p>
  <button id="close-settings">Close</button>
</dialog>

<button id="open-settings">Open settings</button>

The dialog is hidden by default. You open it with JavaScript.

showModal() vs show()

Use showModal() for a true modal. It adds a backdrop, traps focus, and blocks interaction with the page behind it:

const dialog = document.getElementById('settings')

document.getElementById('open-settings').addEventListener('click', () => {
  dialog.showModal()
})

Use show() when you want a non-modal panel. No backdrop, no focus trap. The user can still click the rest of the page.

For most cases, showModal() is what you want.

Closing the dialog

Call close() to dismiss it:

document.getElementById('close-settings').addEventListener('click', () => {
  dialog.close()
})

You can pass a return value:

dialog.close('saved')

Read it later with dialog.returnValue. Handy when a dialog is part of a workflow.

Pressing Escape closes a modal dialog automatically. You do not need to listen for the key yourself.

Forms inside a dialog

Put a form in the dialog and set method="dialog":

<dialog id="confirm-delete">
  <form method="dialog">
    <p>Delete this project?</p>
    <button value="cancel">Cancel</button>
    <button value="delete">Delete</button>
  </form>
</dialog>

Clicking a button submits the form and closes the dialog. The button’s value becomes returnValue. This replaces the old JavaScript confirm pattern for simple yes/no prompts.

Styling the backdrop

Use the ::backdrop pseudo-element to style the dimmed area behind the modal:

dialog::backdrop {
  background: rgba(0, 0, 0, 0.5);
}

The dialog itself styles like any other element. Border, padding, CSS variables for colors. All the usual rules apply.

Why not a div modal?

A homemade div modal needs extra work:

The dialog element with showModal() gives you all of that. It also renders in the browser’s top layer, above everything else. No z-index wars.

My advice is to reach for dialog before you build another div-based modal. It is simpler and more accessible out of the box.

Tagged: HTML · All topics
~~~

Related posts about html: