# The HTML dialog tag

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

Author: [Flavio Copes](https://flaviocopes.com/about/) | Published: 2026-08-18 | Topics: [HTML](https://flaviocopes.com/tags/html/) | Canonical: https://flaviocopes.com/html-dialog-tag/

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

```html
<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:

```js
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:

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

You can pass a return value:

```js
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"`:

```html
<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](https://flaviocopes.com/javascript-confirm/) pattern for simple yes/no prompts.

## Styling the backdrop

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

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

The dialog itself styles like any other element. Border, padding, [CSS variables](https://flaviocopes.com/css-variables/) for colors. All the usual rules apply.

## Why not a div modal?

A homemade `div` modal needs extra work:

- Focus trapping so keyboard users stay inside
- Returning focus to the trigger button on close
- Blocking clicks on the page behind
- Managing z-index stacking

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.
