Confirmations, progress and errors must reach screen readers without moving focus. See how to build live regions for forms, queues and apps.
When a page shows a status message, that message must be programmatically determinable through a role or property, so that assistive technology can present it without the user moving focus to it. A status message here means a change in content that is not a change of context and that tells the user about the result of an action, a waiting state, the progress of a process, or an error.
A sighted visitor sees "Draft saved" appear in a corner. A screen reader user hears nothing, because focus is still on the Save button and nothing told the software to read the new text. The criterion closes that gap.
It does not apply when focus moves to the message, for example to an error summary at the top of a form, because the screen reader announces whatever receives focus.
Public service transactions are full of silent outcomes: a filing receipt, a payment confirmation, an "application saved" note, the place in an online queue. When these are only visual, a resident using a screen reader cannot tell whether the form went through, and may submit it twice or abandon it.
Pay particular attention to long forms with autosave and to anything that updates on a timer.
Visible is not enough; a message must also be audible. The fix is often a single attribute; the real work is finding which messages need it.
Most screen readers watch a region that is already on the page and announce changes to it. A region injected together with its text is often missed. Put an empty status container in the markup and fill it afterwards. Behavior varies a little between screen readers and browsers, so test with real assistive technology.
filingResult.innerHTML =
'<div role="status">Filing received. Case number 24-0817.</div>';<!-- in the page from the start -->
<div id="filing-status" role="status"></div>
<script>
document.getElementById("filing-status").textContent =
"Filing received. Case number 24-0817.";
</script>An online waiting room that announces every number change aggressively makes the page unusable. Use a polite status region and update it at meaningful points.
<div aria-live="assertive" id="pos"></div>
<script>
setInterval(() => pos.textContent = "Position " + n(), 1000);
</script><div role="status" id="pos"></div>
<script>
let last = null;
setInterval(() => {
const now = n();
if (last === null || now % 10 === 0 || now <= 3) {
pos.textContent = "You are number " + now + " in line.";
}
last = now;
}, 1000);
</script>A saved-at note that updates quietly in the corner should be a status message, but not one that interrupts typing every few seconds. Update it when the save completes, and keep the text short.
<span class="saved">Saved 2:14 p.m.</span><span id="save-note" role="status"></span>
<!-- script sets: "Draft saved at 2:14 p.m." after each successful save -->This criterion applies to content implemented with markup languages; in native apps, platform announcements are the equivalent. Native platforms provide announcement calls and live regions. A banner that fades after two seconds is the classic silent message.
// SwiftUI
Button("Place hold") {
holds.append(book)
showBanner = true // visual only
}// SwiftUI
Button("Place hold") {
holds.append(book)
showBanner = true
UIAccessibility.post(notification: .announcement,
argument: "Hold placed for \(book.title)")
}// Jetpack Compose
if (banner) Text("Hold placed")// Jetpack Compose
if (banner) {
Text("Hold placed",
modifier = Modifier.semantics {
liveRegion = LiveRegionMode.Polite
})
}role="alert" for routine confirmations.Ship it when:
Form behavior in general is covered in common barriers.