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
- GreenSnippets
- MIT
<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
<!-- 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.
Related snippets
- CSS
Respect prefers-reduced-motion
Turn off or shorten animations for users who ask their system for less motion.
- CSS
Accessible focus ring with :focus-visible
Show a clear focus outline for keyboard users without drawing it on mouse clicks.
- HTML
Accordion with details and summary
A keyboard-accessible FAQ accordion with no JavaScript, including an exclusive group using the name attribute.
- CSS
Accessible button styles with states
A base button with hover, active, disabled and focus styles that meets minimum target size.

