The Native dialog Element

Build real modals with built-in focus trapping and no library.

For years, modal dialogs meant a pile of custom JavaScript to trap focus, handle the Escape key, and dim the background. The <dialog> element gives you all of that natively.

Two ways to open

  • dialog.show() — opens a non-modal dialog; the page behind stays interactive.
  • dialog.showModal() — opens a true modal: focus is trapped inside, Escape closes it, and the rest of the page becomes inert behind a backdrop.

Closing it

Call dialog.close(), or — the neat trick — put a <form method="dialog"> inside. Submitting that form closes the dialog automatically and even reports which button was pressed via dialog.returnValue.

<dialog id="d">
  <form method="dialog">
    <button value="ok">OK</button>
  </form>
</dialog>

You even get a styleable backdrop for free through the ::backdrop pseudo-element.

Example

Try it yourself
Loading editor…
Press Run to see the result.

When to use it

  • A confirmation dialog uses <dialog> with showModal() so the rest of the page is blocked until the user responds.
  • A login form is placed inside a <dialog> that opens when the user clicks "Sign in" without navigating away.
  • A delete confirmation uses <dialog> with form method="dialog" so clicking Cancel closes it and clicking Delete submits.

More examples

Modal dialog opened by button

showModal() opens the dialog as a top-layer modal with a backdrop; close() dismisses it programmatically.

Example · html
<button id="open-dlg">Open dialog</button>

<dialog id="my-dialog">
  <h2>Confirm action</h2>
  <p>Are you sure you want to proceed?</p>
  <button id="close-dlg">Cancel</button>
  <button>Confirm</button>
</dialog>

<script>
  const dlg = document.getElementById("my-dialog");
  document.getElementById("open-dlg")
    .addEventListener("click", () => dlg.showModal());
  document.getElementById("close-dlg")
    .addEventListener("click", () => dlg.close());
</script>

Dialog with built-in form close

form method="dialog" closes the dialog on submit; returnValue holds the button value for the close handler.

Example · html
<dialog id="confirm-dlg">
  <p>Delete this item permanently?</p>
  <form method="dialog">
    <button value="cancel">Cancel</button>
    <button value="delete">Delete</button>
  </form>
</dialog>

<script>
  const dlg = document.getElementById("confirm-dlg");
  dlg.addEventListener("close", () => {
    if (dlg.returnValue === "delete") {
      console.log("Item deleted");
    }
  });
</script>

Non-modal dialog as a tooltip panel

show() opens the dialog non-modally so the user can still interact with the rest of the page simultaneously.

Example · html
<button id="show-info">Show info</button>

<dialog id="info-panel">
  <h3>Keyboard shortcuts</h3>
  <dl>
    <dt>Ctrl+S</dt><dd>Save</dd>
    <dt>Ctrl+Z</dt><dd>Undo</dd>
  </dl>
  <button id="hide-info">Close</button>
</dialog>

<script>
  const panel = document.getElementById("info-panel");
  document.getElementById("show-info")
    .addEventListener("click", () => panel.show());
  document.getElementById("hide-info")
    .addEventListener("click", () => panel.close());
</script>

Discussion

  • Be the first to comment on this lesson.
The Native dialog Element — HTML | SoundsCode