aria-modal
Tells assistive technology to treat the rest of the page as inert while a dialog is open. Set to "true" on role="dialog" or role="alertdialog". Does not actually make the background inert — pair with the inert attribute or a focus trap.
When to use
On a role="dialog" or role="alertdialog" element that should block interaction with the rest of the page while open. Set aria-modal="true" so the screen reader confines its virtual cursor to the dialog and announces background content as unreachable.
A modal dialog has three responsibilities:
aria-modal="true"— tells assistive technology this is modal.- Background inert — applied via the
inertattribute on the surrounding content, or by JavaScript-managed focus trapping. Without this, keyboard users can tab out of the dialog. - Initial focus — moves focus into the dialog when it opens, and restores focus to the trigger when it closes.
aria-modal alone covers the screen-reader side; it does not stop a keyboard user from tabbing past the dialog. Browser support for inferring inertness from aria-modal is inconsistent, so always combine.
The native HTML <dialog> element with .showModal() handles all three automatically. Prefer it when feasible.
How to keep it in sync
Valid values are "true" and "false". Render "true" while the dialog is open; either remove the attribute or set "false" while it is closed (typically the closed dialog is not in the DOM at all, so the attribute is moot).
aria-modal is paired with two labelling attributes:
aria-labelledby="<dialog-title-id>"— points at the visible heading.aria-describedby="<dialog-body-id>"— optional, for a short description.
Together they give the screen reader a coherent opening announcement: “Dialog, Delete account?, This action cannot be undone.”
Common failures
aria-modal="true"without any focus trap — keyboard users tab into the background.- Using
aria-modalon a non-modal popover or tooltip. Userole="dialog"only for true modal dialogs; a popover is not a dialog. - Missing
aria-labelledby— the screen reader announces “Dialog” with no name. - Failing to move focus into the dialog when it opens.
- Failing to restore focus to the original trigger when it closes.
- Marking the background with
aria-hidden="true"instead ofinert— keyboard focus still escapes; only the screen-reader cursor is constrained. - Two simultaneously-open modals with
aria-modal="true". The accessibility tree gets confused; show one at a time.
Example
<div
role="dialog"
aria-modal="true"
aria-labelledby="confirm-title"
aria-describedby="confirm-body"
>
<h2 id="confirm-title">Delete account?</h2>
<p id="confirm-body">This action cannot be undone.</p>
<button type="button" autofocus>Cancel</button>
<button type="button">Delete</button>
</div>