Video examples
iOS Voiceover
Android Talkback
Windows Jaws Chrome
Windows NVDA Chrome
MacOS Voiceover Safari
Required attributes
Launch button
- Should be a button, not a link
- Upon closing, focus must return to the button that launched the dialog
- Do not use
aria-haspopup
. This attribute has very low and support and unpredictable output across screen readers.
Name
- The modal window has a logical descriptive name from either:
aria-label="Modal title"
oraria-labelledby="heading-id"
pointing to an<h2>
as a title
Role
- Use
role="dialog"
so the screen reader can identify this as a dialog or modal
Group
- Upon closing, focus must return to the button that launched the dialog
State
- Use
aria-modal="true"
to indicate content beneath the modal is inert and that the screen reader must not browse outside the dialog.
Focus
- Use
tabindex="-1"
to make the modal itself targetable for focus - Upon closing, focus must return to the button that launched the dialog
Documentation
Screenreader differences
- NVDA
- By default, NVDA may read the entire modal upon launch. This is expected behavior.
Code examples
Use semantic HTML where possible
Browser support for <dialog>
is still incomplete.
Some browsers require additional scripting. This simple example works in Chrome, but may not work correctly in all browsers such as Safari and Firefox.
<button id="showModal">
Things you should know
</button>
<dialog role="dialog"
id="modal"
tabindex="-1"
aria-modal="true"
aria-labelledby="dialog-title">
<button type="button"
id="closeModal"
class="close">
<span class="hidden">Close</span>
</button>
<div class="dialog-content">
<h2 id="dialog-title" class="h-bravo">
Things you should know
</h2>
<h3>Keyboard</h3>
<ul>
<li>Focus must not enter the rest of the page.</li>
<li>The escape key must close the modal.</li>
</ul>
<h3>Screenreader</h3>
<ul>
<li>The modal's title is announced on launch.</li>
<li>The screen reader cannot read content behind the dialog.</li>
</ul>
<button type="submit">
Continue
</button>
</section>
</dialog>