role=“status”, role=“alert” and role=“log” Compared
Permalink to "role=“status”, role=“alert” and role=“log” Compared"status, alert and log are ARIA roles that create live regions with built-in defaults, so authors do not have to remember the right combination of aria-live, aria-atomic and aria-relevant. Each fits one kind of message. The common failure is using alert for everything — “Saved”, “12 results”, “Sorted” — so every status interrupts whatever the user was listening to, and the genuinely urgent message is indistinguishable from the rest.
This page compares the three roles, their defaults and their intended uses in data interfaces. It belongs to ARIA live regions for dynamic data and complements choosing between polite and assertive aria-live regions.
Spec reference
Permalink to "Spec reference"| Role | Implicit aria-live |
Implicit aria-atomic |
Implicit aria-relevant |
Purpose (ARIA 1.2) |
|---|---|---|---|---|
status |
polite |
true |
additions text |
Advisory information that is not important enough to justify an alert |
alert |
assertive |
true |
additions text |
Important, usually time-sensitive information |
log |
polite |
false |
additions |
New information added in meaningful order, where old information may disappear |
A related role, marquee, is off by default and exists for non-essential scrolling content; timer is also off. Neither is useful for data interfaces in practice.
SC 4.1.3 Status Messages is satisfied by any of the three, provided the message is present in the region’s content. The understanding document’s examples map neatly: a search result count is a status, an error preventing submission can be an alert, and a chat transcript is a log.
When to use each role — and when not to
Permalink to "When to use each role — and when not to"status is the default for a data interface. Almost every message a table or dashboard produces is the result of something the user just did, and the user is waiting for it: they will hear it as soon as the current utterance ends.
alert is for problems with a cost to waiting. A failed save that the user does not hear about is data loss. A session timeout warning they hear thirty seconds late may be too late. Keep the list of alert-worthy events short and explicit.
log is for sequences: an import progress feed, an activity stream, a chat panel, streaming log lines. Only the newly appended entry is read; earlier entries stay available for reading but are not repeated. The full treatment is in accessible live log viewers.
Do not use alert for validation errors that appear as the user types. Each keystroke that toggles an error interrupts their typing feedback. Attach field errors with aria-describedby and announce a summary only on submit.
Annotated code example
Permalink to "Annotated code example"<!-- One of each, rendered with the page and never removed -->
<!-- SC 4.1.3: routine results; polite + atomic by role -->
<div role="status" class="visually-hidden" id="sr-status"></div>
<!-- SC 4.1.3: urgent problems only; assertive + atomic by role -->
<div role="alert" class="visually-hidden" id="sr-alert"></div>
<!-- A visible activity feed: polite, additions only, not atomic -->
<ol role="log" aria-label="Import progress" id="import-log"></ol>
// A tiny router so call sites choose intent, not ARIA
const regions = {
status: document.getElementById('sr-status'),
alert: document.getElementById('sr-alert'),
};
export function notify(message, { urgent = false } = {}) {
const el = urgent ? regions.alert : regions.status;
el.textContent = '';
requestAnimationFrame(() => { el.textContent = message; });
}
// Call sites
notify('Sorted by Amount, descending.'); // status
notify('Could not save row INV-1042. Changes kept locally.', { urgent: true }); // alert
// Log entries are appended, never replaced
function logLine(text) {
const li = document.createElement('li');
li.textContent = text;
document.getElementById('import-log').append(li); // only this is read
}
Routing by intent — urgent: true — keeps ARIA decisions in one place. Engineers deciding whether a message is urgent is a product question; engineers remembering which role is assertive is an avoidable bug.
Keyboard & AT behaviour
Permalink to "Keyboard & AT behaviour"| Region | NVDA | JAWS | VoiceOver | TalkBack |
|---|---|---|---|---|
status |
Queued after current speech | Queued | Queued; may drop if another arrives quickly | Queued |
alert |
Interrupts | Interrupts | Interrupts | Queued on some versions |
log append |
New entry only | New entry only | New entry only | New entry only |
alert inserted with text |
Usually spoken (special-cased) | Usually spoken | Usually spoken | Varies |
The last row is a quirk worth knowing: browsers special-case role="alert" so that an alert element inserted into the page with its text already present is announced. That makes alert more forgiving than status, and is part of why it gets overused. Do not let the quirk drive the role choice.
Integration context
Permalink to "Integration context"In React and other component frameworks, render the regions once at the root and expose a notify function; live regions in React without lost announcements shows the pattern. For many competing messages from one action, queueing and merging are covered in announcement queues for competing messages.
The implicit defaults are why aria-atomic and aria-relevant rarely need setting explicitly: status and alert are already atomic, and log already reads only additions.
Gotchas
Permalink to "Gotchas"aria-live="assertive" on role="status". Explicit attributes override the role’s defaults, producing an assertive status. Occasionally deliberate, usually a copy-paste accident.
Alerts that repeat. A persistent error banner with role="alert" that is re-rendered on every state change re-announces on every render. Render it once and change it only when the error changes.
Visible alerts that steal focus. An alert should not also move focus; the whole point is that the message is heard without focus moving. If the user must act, use a dialog.
Testing checklist
Permalink to "Testing checklist"FAQ
Permalink to "FAQ"What is the difference between role="status" and role="alert"?
Both are live regions that read their whole content, but status is polite — it waits for current speech to finish — while alert is assertive and interrupts. Use status for routine results and alert only for urgent problems.
Do I need aria-live on an element with role="status"?
No. role=“status” already implies aria-live=“polite” and aria-atomic=“true”. Adding aria-live only matters if you intend to override those defaults, which is rarely the right call.
When should I use role="log"?
For content that grows as a sequence — activity feeds, import progress, chat, streaming logs — where only the newest entry should be read and earlier entries remain available in the page.
Why is role="alert" announced even when it is added with text already inside?
Browsers special-case alerts so that inserting an alert element fires an alert event. That makes alerts forgiving, but it is not a reason to use alert for non-urgent messages.
Related
Permalink to "Related"- Polite versus assertive — the politeness decision underneath
- aria-atomic and aria-relevant — the defaults each role sets
- Accessible live log viewers — role=“log” in depth