Dialog
A modal window on the native dialog element: the rest of the page is inert, focus stays inside, and closing it returns focus to where it came from.
Demo
Why it is accessible
Modal windows tend to be traps: keyboard focus leaks out into the page underneath them, a screen reader reads content that isn't visible, and closing the window leaves you back at the top of the page. The native dialog element, opened with the showModal() method, solves all three problems on its own: the rest of the page becomes inert, focus cannot escape the window, Escape closes it, and the browser returns focus to the button that opened it.
The window takes its name from its heading, so a screen reader announces what it is as soon as it opens. It has no fixed height: if the content is longer than the screen, it scrolls inside the window, not underneath it.
Test it yourself
Keyboard
- Tab to the button; Enter opens the window.
- Tab and Shift+Tab cycle only between the elements inside the window.
- Escape closes the window, and focus returns to the original button.
Screen reader
- On opening you hear “dialog, Terms of engagement” and the heading.
- The virtual cursor cannot move onto the page content underneath the window.
Zoom and reflow
- At 400% zoom the window fills almost the whole screen, and its content scrolls inside the window.
Without JavaScript
The window is rendered already open, directly in the page, as a plain box of content. The button that opens it isn't shown, because it would have nothing to do.
Code to copy
<ad-dialog>
<button type="button" class="button" data-dialog-open>Show terms of engagement</button>
<dialog open aria-labelledby="terms-title">
<h2 id="terms-title">Terms of engagement</h2>
<p>…</p>
<form method="dialog" class="dialog__actions">
<button class="button">Close</button>
</form>
</dialog>
</ad-dialog>
<link rel="stylesheet" href="/assets/js/components/ad-dialog/ad-dialog.css">
<script type="module" src="/assets/js/components/ad-dialog/ad-dialog.js"></script>