aria-modal — Indicating Modal Dialogs to Screen Readers
In this tutorial, you will learn about aria. We cover key concepts, practical examples, and best practices to help you master this topic.
aria-modal indicates that a dialog element is modal, meaning content outside the dialog is inert and cannot be interacted with until the dialog is dismissed.
In this tutorial, you'll learn how to use aria-modal in ARIA dialog implementations.
What You'll Learn
By the end of this lesson, you'll understand when to use aria-modal, how it differs from aria-hidden, and how to implement accessible modal dialogs.
Why It Matters
Modal dialogs trap focus and prevent interaction with the rest of the page. Without aria-modal, screen reader users may not realize the background is inactive.
Real-World Use
Doda Browser's settings dialog uses aria-modal="true" with role="dialog" so screen reader users know they must dismiss the dialog before interacting with the main page.
Modal Dialog Flow
flowchart TD
A[Dialog opens] --> B[Set aria-modal='true']
B --> C[Trap focus in dialog]
C --> D[Make background inert]
D --> E[Screen reader announces dialog]
E --> F{User dismisses dialog}
F -->|Yes| G[Remove aria-modal]
G --> H[Restore focus to trigger]
H --> I[Restore background interaction]
How aria-modal Works
aria-modal="true" tells screen readers that content outside the dialog is not available for interaction:
<div role="dialog" aria-modal="true" aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm Scan</h2>
<p>Are you sure you want to scan all files?</p>
<button onclick="confirmScan()">Yes</button>
<button onclick="closeDialog()">Cancel</button>
</div>
aria-modal vs aria-hidden
aria-modal communicates the modality to screen readers. You must also physically prevent interaction with the background:
function openDialog(dialog) {
dialog.setAttribute('aria-modal', 'true');
dialog.hidden = false;
// Make background inert
document.getElementById('page-content').inert = true;
// Trap focus in dialog
trapFocus(dialog);
// Focus the first focusable element
focusFirstElement(dialog);
}
function closeDialog(dialog) {
dialog.removeAttribute('aria-modal');
dialog.hidden = true;
// Restore background
document.getElementById('page-content').inert = false;
// Return focus
document.getElementById('open-dialog-btn').focus();
}
Native Dialog Element
The HTML <dialog> element has implicit dialog role and handles some modal behavior:
<dialog id="confirm-dialog" aria-labelledby="confirm-title">
<h2 id="confirm-title">Confirm</h2>
<p>Proceed with scan?</p>
<button onclick="this.closest('dialog').close()">Cancel</button>
<button onclick="runScan()">Scan</button>
</dialog>
Common Mistakes
- Using aria-modal without focus trapping: The modal must physically trap keyboard focus.
- Using aria-modal on non-dialog elements: Only use it with role="dialog" or role="alertdialog".
- Forgetting to make the background inert: Use the inert attribute or manually disable background elements.
- Not restoring focus when the dialog closes: Focus should return to the element that opened the dialog.
- Using aria-modal="false": The default is false. Only add the attribute when true.
Practice and Challenge
1. What does aria-modal="true" tell screen readers? That content outside the dialog is not available for interaction.
2. What ARIA role must be paired with aria-modal? role="dialog" or role="alertdialog".
3. What must you do in addition to setting aria-modal? Trap keyboard focus and make background content inert.
4. What HTML element provides built-in dialog semantics?
The <dialog> element.
5. Challenge: Build a modal dialog component with aria-modal. Include focus trapping, inert background, and focus restoration on close.
FAQ
Mini Project
Build a complete modal dialog system with aria-modal, focus trapping, inert background, and Escape key dismissal. Test with NVDA and VoiceOver.
What's Next
Continue to aria-pressed to learn about toggle button state.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro