<dialog> Modals
Overview
Building accessible Pop-up Modals in React or Vanilla JS is notoriously difficult. You have to trap keyboard focus, prevent scrolling on the body, handle the Escape key, and deal with Z-index hell. The native <dialog> element solves all of this natively. When opened as a 'modal', it automatically dims the background, traps focus inside the box, sits securely on the absolute top layer of the browser (ignoring all z-indexes), and can be dismissed via the Escape key.
Syntax
<!-- The native modal element -->
<dialog id="delete_modal">
<h2>Are you absolutely sure?</h2>
<p>This action cannot be undone.</p>
<!-- A form with method="dialog" automatically closes the modal on submit! -->
<form method="dialog">
<button value="cancel">Cancel</button>
<button value="confirm" style="color: red;">Delete Account</button>
</form>
</dialog>
<!--
Triggering it requires a tiny bit of JS,
or you can use modern Invoker Commands (see next topic).
-->
<button onclick="document.getElementById('delete_modal').showModal()">
Delete
</button>Common Pitfalls
- Using
dialog.show()instead ofdialog.showModal().show()just makes the dialog visible inline, like a normal<div>.showModal()elevates it to the special Top Layer, traps focus, and activates the background backdrop. - Forgetting to style the
::backdroppseudo-element. By default, the modal background dimming might be too light. You must styledialog::backdrop { background: rgba(0,0,0,0.5); }.
Interview Questions
The Top Layer is a special, isolated rendering context provided by the browser (used for Fullscreen APIs and <dialog>). Anything in the Top Layer is guaranteed to render above absolutely everything else, completely bypassing normal CSS z-index stacking contexts.
Real-World Example
A completely accessible newsletter signup modal.
<dialog id="newsletter">
<h3>Join our Newsletter</h3>
<form method="dialog">
<!-- Using method="dialog" means this button just closes the modal -->
<button type="submit" aria-label="Close">X</button>
</form>
<form action="/api/subscribe" method="POST">
<input type="email" required placeholder="you@company.com">
<button type="submit">Subscribe</button>
</form>
</dialog>Check Your Knowledge
Test your understanding of <dialog> Modals with these quick questions.