WCAG 4.1.3 · Level AA · ADA Title II

Status message announcements and the ADA

Confirmations, progress and errors must reach screen readers without moving focus. See how to build live regions for forms, queues and apps.

Messages that arrive without focus

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.

Confirmations that nobody hears

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.

The live region must exist first

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.

Incorrect
filingResult.innerHTML =
  '<div role="status">Filing received. Case number 24-0817.</div>';
Correct
<!-- 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>

Queue updates without the noise

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.

Incorrect
<div aria-live="assertive" id="pos"></div>
<script>
  setInterval(() => pos.textContent = "Position " + n(), 1000);
</script>
Correct
<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>

Autosave notes on long applications

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.

Incorrect
<span class="saved">Saved 2:14 p.m.</span>
Correct
<span id="save-note" role="status"></span>
<!-- script sets: "Draft saved at 2:14 p.m." after each successful save -->

Announcements in native apps

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.

Incorrect
// SwiftUI
Button("Place hold") {
    holds.append(book)
    showBanner = true   // visual only
}
Correct
// SwiftUI
Button("Place hold") {
    holds.append(book)
    showBanner = true
    UIAccessibility.post(notification: .announcement,
                         argument: "Hold placed for \(book.title)")
}
Incorrect
// Jetpack Compose
if (banner) Text("Hold placed")
Correct
// Jetpack Compose
if (banner) {
    Text("Hold placed",
         modifier = Modifier.semantics {
             liveRegion = LiveRegionMode.Polite
         })
}

A test routine

  1. Trigger each action that produces feedback: submit, save, add, filter, upload, wait. Do it with a screen reader running and with focus staying where it was.
  2. Listen: the message should be spoken once, soon after it appears, without you moving to it.
  3. Inspect the DOM and confirm the live region or role exists before the text is inserted.
  4. Check urgency. Errors may interrupt; confirmations and progress should be polite.
  5. Make sure nothing speaks repeatedly or on a rapid timer.

Common mistakes and a ship-it list

  • Injecting the region and its text in the same step.
  • Using role="alert" for routine confirmations.
  • Moving focus to a toast and trapping the user there.
  • Updating a live region several times per second.
  • Removing the message from the DOM after one second, before it can be read.

Ship it when:

  • Every outcome message is exposed with a role or live region.
  • Regions exist at load and are updated afterwards.
  • Urgent errors use alert and everything else uses polite status.
  • Messages stay long enough to be read and are not repeated.

Form behavior in general is covered in common barriers.

Sources

Standard version: WCAG 2.1 (W3C Recommendation, 5 June 2018), as named in the Title II web rule. This page is for informational purposes only and is not legal advice. For binding requirements, refer to the official ADA statute and regulations, and ask a lawyer how they apply to you.

Corpowid is recognized by Gartner

Corpowid has been recognized by Gartner, a leading global research and advisory firm, for our innovation and performance in digital accessibility. These badges reflect our commitment to creating inclusive, AI-powered web experiences.

Have questions about Corpowid?

Let’s connect.

We will get back to you as soon as possible.