# Alerts that cut off VoiceOver for routine updates

Source: https://easeweb.dev/learn/urgent-alerts
Topics: Live updates > Only urgent messages interrupt; routine updates wait their turn (WCAG 4.1.3)
The fix: Write routine notices into a role="status" region, which waits until the screen reader has finished what it is saying, and keep a separate role="alert" region for the few messages that can't wait, such as a lost connection. Both regions are on the page, empty, from the start, and neither takes focus.
Test with: screen reader, keyboard
References: https://www.w3.org/WAI/WCAG22/Understanding/status-messages.html https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA22 https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA19 https://www.w3.org/TR/wai-aria-1.2/#aria-live https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Roles/alert_role https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-live https://webaim.org/projects/screenreadersurvey10/

This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.

## What happens

A team's planning app shows one task at a time: its title, its due date and a few lines on what to do. Across the top of the page runs a thin notice bar. When a teammate opens the same task, it says "Sam opened this task". When the due date moves, "Sam changed the due date to 14 May". When a comment arrives, "New comment from Alex". And if the connection drops, "Connection lost. Changes you make now won't be saved." The script writes every one of them into the same element, and that element has `role="alert"`.

A VoiceOver user on an iPad is reading the task line by line. Partway through the first line, VoiceOver stops and says "Sam opened this task." They go back to the line and start again, and a few words in, "Sam changed the due date to 14 May." Then the comment. Each notice is short and harmless, and each one breaks off the sentence they were in. When the connection really does drop, the warning sounds exactly like the three notices before it.

A JAWS or Narrator user on a laptop hears something else: each line in full, then the notice that arrived during it. Nothing is cut off, but the alert role makes no difference either. "Connection lost" waits for the end of the line, as "Sam opened this task" did, and is read in the same voice.

## Why it fails

`role="alert"` is an assertive live region. ARIA says updates to an assertive region have the highest priority and should be presented immediately, and it lets the screen reader drop messages that were waiting. That is what a message people must act on needs, and what a routine notice must not have. Success criterion 4.1.3 asks that status messages can be presented to people without receiving focus, and its Understanding page says the point is to do it "in a way that doesn't unnecessarily interrupt their work". It lists using `role="alert"` or `aria-live="assertive"` on content that is not important and time-sensitive among its failures, though no technique page for that failure has been written yet. "Sam opened this task" is neither important nor time-sensitive. Screen readers don't all do what the region asks. In the 2026 releases, VoiceOver on macOS and iPadOS cut in for assertive regions and alerts, and on macOS stopped reading. NVDA, tested in Firefox, cut in for `role="alert"` too, read the message with the word "alert", then read again what it had cut off. JAWS and Narrator read alerts as they read polite regions, once the sentence or line in progress had ended. The developer chose the alert role because it is the one that is sure to be heard, and nothing in the browser warns that it is also the one that interrupts.

## Who is affected

The notices arrive whether or not the person did anything, so the more people work on the same tasks, the more often a VoiceOver user is interrupted. Most screen reader users on phones and tablets use VoiceOver: 70.6% of the mobile respondents in WebAIM's 2024 survey, against 9.7% who named it as their main screen reader on a computer. A sighted user glances at the bar, or ignores it, and keeps reading.

## What automation and AI miss

A scan finds the live region, sees it on the page from the start, and passes it: whether a message is urgent is a matter of meaning, and no rule can read that. The audit flags an empty `role="alert"` or `aria-live="assertive"` region that waits for messages outside a form or dialog, unless its id or class names it for errors, so that a person checks what goes into it, but it can't see the messages until the app sends them. AI assistants asked to make notifications accessible may put `role="alert"` on all of them, for the same reason the developer did. Only listening while the notices arrive shows the interruptions, and only in a screen reader that honours them.

## Before: every notice in one alert region

```html
<div id="notices" class="notices" role="alert"></div>
```

```js
const notices = document.querySelector('#notices');

function notify(text) {
  notices.textContent = text;
}

presence.on('open', (name) => notify(`${name} opened this task`));
task.on('due', (change) => notify(`${change.by} changed the due date to ${change.due}`));
comments.on('new', (comment) => notify(`New comment from ${comment.author}`));
window.addEventListener('offline', () => notify('Connection lost. Changes you make now won’t be saved.'));
```

The region is on the page from the start, so every notice is announced, and every notice is announced as an alert. VoiceOver, and NVDA in Firefox, break off the sentence for "Sam opened this task" just as they do for "Connection lost", and in JAWS and Narrator the two sound the same.

## After: a status region for routine notices, an alert region for urgent ones

```html
<div class="notices">
  <p id="notice-status" role="status"></p>
  <p id="notice-alert" role="alert"></p>
</div>
```

```js
const statusRegion = document.querySelector('#notice-status');
const alertRegion = document.querySelector('#notice-alert');

function notify(text, { urgent = false } = {}) {
  (urgent ? alertRegion : statusRegion).textContent = text;
}

presence.on('open', (name) => notify(`${name} opened this task`));
task.on('due', (change) => notify(`${change.by} changed the due date to ${change.due}`));
comments.on('new', (comment) => notify(`New comment from ${comment.author}`));
window.addEventListener('offline', () => notify('Connection lost. Changes you make now won’t be saved.', { urgent: true }));
```

Routine notices now go to the status region. `role="status"` is a polite live region: the screen reader finishes the line it is reading, then says "Sam opened this task." The one message that can't wait still goes to the alert region, so in VoiceOver and NVDA it still cuts in, and because it is now the only thing that ever does, it stands out. In JAWS and Narrator nothing changes in when the messages are read, so the warning's own words carry the urgency: "Connection lost" comes first, then what it means for the person's changes. Both regions are in the HTML, empty, from the start, and the notice bar looks exactly as it did. Each call site says which kind of message it sends, so the choice is made once, where the message is written.

## Implementation decisions

**Which messages are urgent.** A message is urgent when the person is about to lose something or must act now: a lost connection, a save or payment that failed, a session about to end, an error that blocks what they are doing. Everything else is routine: saved, added, updated, someone joined, a new comment. When you are not sure, it is routine. If a message is urgent but nobody could act on it, ask whether it needs to be said at all.

**The opposite mistake.** An urgent message in a polite region waits until the screen reader has finished speaking, and may wait behind other notices. A warning that a session is about to end is the usual case. The warning, and the way to extend the session, are covered in [session timeouts with no warning or way to extend](/learn/time-limits).

**The words carry the urgency.** Since JAWS and Narrator read an alert as they read a status message, an urgent message has to sound urgent in words: say what happened in the first two or three words ("Connection lost", "Payment failed"), then what it means and what to do. Keep it on screen until it is no longer true, rather than letting it disappear with the next notice, so people who reach the bar later still find it.

**Two regions, not one that switches.** Keep a status region and an alert region side by side, rather than one region whose `aria-live` the script changes before each message. With two fixed regions, a message can never go out with the politeness that was set for the one before it.

**Notices that come together.** Writing into a region replaces what was there. A routine notice that arrives a moment after another can replace it before it is read, so when both matter, join them into one message ("Sam opened this task and changed the due date to 14 May") or keep the last few as lines in the bar. Several alerts at once are worse: ARIA lets the screen reader drop messages that were waiting when an assertive one arrives, so only the last may be heard. MDN warns that several alerts at once, and unnecessary alerts, create bad user experiences.

**Notification and toast components.** Many let you choose the role for each kind of message. Check what yours does by default, since some render every message as an alert. Map success and information messages to status, and only the errors that need action now to alert. How long a toast stays on screen is a separate question, covered in [toasts that vanish before you can read or undo them](/learn/toast-timing).

**Clear an alert when it is no longer true.** When the connection comes back, empty the alert region and write "Back online" into the status region. A warning left in place is read again by anyone who moves through the bar later, and it still says their changes won't be saved.

**Not fixes.** Moving focus to the notice gets it read in every screen reader, but it takes people away from what they were reading, for every notice, which is worse than the interruption. Taking the notices out of the live region altogether stops the interruptions, but then "Connection lost" is never heard either. A region that is added to the page together with its message is often not announced at all: that failure is covered in [status messages that are shown but never announced](/learn/status-messages).

## Verify the fix

1. Inspect the DOM before any notice arrives: a `role="status"` region and a `role="alert"` region are present, empty, and not hidden with `display: none` or `aria-hidden`.
2. With VoiceOver, or NVDA in Firefox, read the task line by line while someone else, in a second browser, opens the task, changes its due date and comments on it. Each notice is read after the line ends, and no line is cut off.
3. Go offline in the developer tools. In VoiceOver, "Connection lost" interrupts at once; in JAWS or Narrator, it is read once the line ends. In each, it starts with what happened and says what it means for the person's changes. Go back online, and the warning is cleared.
4. Search the code for `role="alert"`, `aria-live="assertive"` and the notification component's settings. Every message that can reach them needs action now.

Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the notification component, or the list of messages it sends, changes.

## Limits

Live regions behave differently across screen readers and browsers, and from one version to the next: what this guide describes is how the releases current in 2026 behaved. Understanding 4.1.3 also notes that assistive technology may delay, suppress or transform status messages to suit its user's settings. Whether a message is urgent is a judgement about the product, which only its team can make. This guide covers notices that arrive while someone is reading. A message that is never announced is covered in [status messages that are shown but never announced](/learn/status-messages), a clock that announces every second in [countdown timers that screen readers keep reading out](/learn/countdown-timers), and dialogs that ask people to confirm in [confirmation dialogs that don't read out their question](/learn/confirmation-dialogs). Letting people put off interruptions altogether, at Level AAA, is a topic of its own. Test with the screen readers your users use.

---

Get this guide in your coding agent: MCP https://easeweb.dev/mcp (setup at https://easeweb.dev/services/developers)
