Accessibility

a11y/dialog-native

Build dialogs on the native <dialog> element opened with showModal() rather than a div with role="dialog".

minorstaticWCAG 2.4.3, 4.1.2 · Afe-a11y-dialog

Why

A div dialog needs a hand-written focus trap, Escape handling, a way to hide the rest of the page from screen readers, and focus return. Each is a common source of bugs. <dialog> with showModal() does all of it and is Baseline widely available.

Fix

Render <dialog>, open it with dialog.showModal() (modal) or dialog.show() (non-modal), close it with dialog.close() or a <form method="dialog">, and style the overlay with ::backdrop. Keep a component library's dialog if the project uses one; check it renders <dialog> or implements the APG pattern.

Examples

<!-- bad -->
<div class="modal" role="dialog" aria-modal="true">…</div>
<!-- good -->
<dialog aria-labelledby="t"><h2 id="t">Newsletter</h2>…</dialog>
<script type="module">document.querySelector('dialog').showModal()</script>

Sources

Facts

Id
a11y/dialog-native
Severity
minor
Check
static checked in the source by audit
Applies to
html angular vue svelte astro jsx
WCAG 2.2
2.4.3, 4.1.2, level A
Taught by the skill
fe-a11y-dialog Dialogs and modals
Since version
0.1.0

Rule file on GitHub

Read it in the terminal

npx github:dawidolko/frontend-skills explain a11y/dialog-native