Skip to content
GreenSnippets

Accessible modal with the dialog element

Use the native dialog element for a modal with built-in focus trapping, Escape to close and a backdrop.

HTML
<button type="button" id="open-dialog">Delete account</button>

<dialog id="confirm" aria-labelledby="confirm-title">
  <form method="dialog">
    <h2 id="confirm-title">Delete your account?</h2>
    <p>This cannot be undone.</p>
    <button value="cancel" autofocus>Cancel</button>
    <button value="confirm">Delete</button>
  </form>
</dialog>

<script>
  const dialog = document.getElementById("confirm");
  document.getElementById("open-dialog").addEventListener("click", () => dialog.showModal());
  dialog.addEventListener("close", () => {
    if (dialog.returnValue === "confirm") console.log("Deleting…");
  });
</script>

Example / expected output

Output
<!-- Style the backdrop with dialog::backdrop { background: rgb(0 0 0 / 0.5); } -->

How it works

showModal() makes the rest of the page inert, traps focus, closes on Escape and returns focus to the opener, all without a library. Label the dialog with aria-labelledby. A form with method="dialog" closes the dialog and reports which button was pressed in dialog.returnValue.

This snippet has been reviewed but was not executed by an automated test. Test it in your own environment before relying on it.