ARIA in Practice · 4 / 8
lesson 4

Live regions

How to tell a screen reader 'something just changed' — and which kind of nudge to use.

~ 17 min read·lesson 4 of 8
0 / 8

A live region is a part of the page whose content can change after the page has loaded, and which a screen reader should announce when it does. Form successes, error toasts, "saving..." indicators, chat messages — all candidates.

The naive approach — just dropping new text into the DOM — does nothing for screen readers. They've already moved on. You have to mark the region as live so the assistive technology watches it. There are two ways to do that, and three knobs to tune behavior. Let's walk through each.

Polite vs assertive

The base attribute is aria-live, with two useful values:

  • aria-live="polite" — wait until the user is idle, then announce. This is the default polite behavior; the announcement queues up rather than interrupting whatever the screen reader is reading right now. Use this for almost everything.
  • aria-live="assertive" — interrupt whatever the screen reader is currently saying and announce immediately. Use this only for truly urgent messages: session timeout warnings, validation errors that block a critical action, real-time emergencies.

There's also aria-live="off", which is the same as having no aria-live attribute at all.

live-regions.html
<!-- Polite: announced when the screen reader has a moment -->
<div aria-live="polite" id="save-status"></div>

<!-- Assertive: interrupts everything -->
<div aria-live="assertive" id="session-warning"></div>

A common mistake is reaching for assertive because it sounds more reliable. It's not — it's more interrupting. Constant interruptions train screen-reader users to mute your tab. Default to polite and earn assertive for genuine emergencies.

Tip

Empty live regions must exist before the change. Adding the aria-live attribute and the new content in the same render is unreliable — many screen readers treat the region as new and skip the announcement. Render the region empty, then update its text.

role="status" and role="alert"

There are two role-based shortcuts that bake in common live-region settings:

  • role="status" is equivalent to aria-live="polite" plus aria-atomic="true". Use it for confirmation messages — "Saved," "Copied to clipboard."
  • role="alert" is equivalent to aria-live="assertive" plus aria-atomic="true". Use it for urgent, critical messages.
status-vs-alert.html
<div role="status">Profile saved.</div>

<div role="alert">Connection lost — your changes are not being synced.</div>

Both roles also imply landmark-ish semantics in some screen readers, which is generally a good thing — they're discoverable, not just announced once. Prefer them over hand-rolling aria-live unless you need to tune the other knobs below.

aria-atomic

When the content of a live region changes, the screen reader has a choice: read the whole region, or read only what changed. aria-atomic controls that.

  • aria-atomic="false" (default) — only the changed text is announced.
  • aria-atomic="true" — the entire region is re-read every time, as one unit.

This matters most for compound messages like a clock or counter. Imagine a timer:

atomic.html
<!-- Without aria-atomic, only the changed digit might be read: "5" -->
<div aria-live="polite">
Time remaining: <span id="seconds">12</span> seconds
</div>

<!-- With aria-atomic, the full sentence is announced each tick -->
<div aria-live="polite" aria-atomic="true">
Time remaining: <span id="seconds">12</span> seconds
</div>

The role="status" and role="alert" shortcuts already set aria-atomic="true" for you, which is almost always what you want for short messages.

aria-relevant

aria-relevant says which kinds of changes count. The values are space-separated tokens: additions, removals, text, or all. The default is additions text — added nodes and changed text. You can broaden it with removals (announce when something is deleted) or use all.

In practice, you almost never need to set aria-relevant. The default does the right thing for the typical "show a toast" or "append a chat message" pattern. Mention it on a code review when you see it being changed without a strong reason — it's one of the more bug-prone ARIA attributes.

DOM change add / remove / textaria-relevant does it count?aria-atomic whole or part? screen reader announces
When the content of a live region changes, atomic decides what is read; relevant decides which kinds of changes are even watched.

Pitfalls

A short list of things that bite people:

  1. Empty region must exist first. Render the live region in the initial HTML, then update its text. Adding the region and the text together often produces silence.
  2. Don't pile up live regions. One per logical purpose. If you have ten different toasts trying to announce themselves at once, switch to a single shared toast region.
  3. Hidden ≠ off. A live region inside a display: none parent is not announced when text changes. If you want a region announced even when it's visually hidden, use the .visually-hidden technique (lesson 5), not display: none.
  4. role="alert" is loud. It interrupts. Save it for genuine "you need to act now" messages.
  5. Test with a real screen reader. Browser devtools won't show you whether your live region actually announces. NVDA on Windows or VoiceOver on macOS will.
Watch out

A toast that fires every time a user clicks a button is rarely useful and often harmful — it interrupts whatever the screen reader was reading. Confirm only meaningful changes, not every interaction.

Try it yourself

check your understanding
You're showing a "Saved." confirmation in the corner of the page. Which is the right primitive?
check your understanding
A timer counts down: "Time remaining: 9 seconds, 8 seconds, 7 seconds." Which attribute makes the screen reader announce the full sentence each tick?
check your understanding
Which is true about aria-live="assertive"?
check your understanding
Why might a fresh live region you just inserted into the DOM not announce?
check your understanding
What's the practical difference between role="status" and role="alert"?
← prevnext lesson →
KeepLearningcertificate
for completing
ARIA in Practice
0 of 8 read