Skip to content
ExamsLibraryFor agentsConnect your agent

What screen readers hear, and the WCAG numbers

intermediate·8 min·Markdown for agents

What this lesson teaches

Announce changes with the quietest mechanism that works, hide things the right way, and cite the WCAG 2.2 thresholds that turn an opinion into a finding.

  1. 1The ladder: stop at the first rung that fits
  2. 2Making the region actually speak
  3. 3Hiding, two opposite ways
  4. 4Alt text by purpose
  5. 5The numbers that make a finding

Below is a transcript of a reading an invoice aloud. It presses Save by itself once a lap; flip the mode, or press Save yourself mid-sentence.

Polite: “Changes saved” waits for the sentence to end. Right for success, counts and loading.

Polite waits for the sentence to end. Assertive interrupts it.

A sighted person sees "Saved" appear. A screen-reader user hears it only if something announces it, and how it is announced decides whether it helps or barges in.

The ladder: stop at the first rung that fits

  1. Focus moves there anyway

    An opened dialog, the first invalid field after Submit. Moving focus is the announcement. Add nothing.
  2. It belongs to one control

    A field's error, a character count: aria-describedby on the input, so it is read with the field.
  3. Not urgent, not tied to a control

    A toast, "Saved", "12 results", "Loading…": a polite , role="status".
  4. Urgent, not tied to a control

    A form-level failure, a session about to expire: role="alert", and nothing else gets it.

role="status" is the polite one; role="alert" is assertive and interrupts. Default to polite. The common over-correction is an assertive success toast: "Saved" now cuts off whatever the user was listening to.

Making the region actually speak

Live regions are fussy. Three rules make them reliable:

  • Render the region empty first, then change its text. A region that mounts already holding its message is announced inconsistently.
  • Keep messages short and whole. The region re-reads everything inside it on each change.
  • Never move focus to a toast. Announce it; leave focus where the person is working.

✕ Before

{msg && <div role="status">{msg}</div>}

✓ After

<div role="status" className="sr-only">{msg}</div>

For loads, put aria-busy="true" on the updating area, say "Loading…" politely, then the outcome: "Loaded, 12 results".

Hiding, two opposite ways

You wantUse
Invisible on screen, still read aloud.sr-only: 1px box, clip-path: inset(50%), white-space: nowrap. One pixel, not zero: some readers skip empty boxes
Visible on screen, not read aloudaria-hidden="true" on decorative icons and visual duplicates

Never put aria-hidden on or above a button, link or input. Tab still lands there, and the reader says nothing exists. To hide something interactive, use inert.

Alt text by purpose

The imagealt
Decorative, or repeats nearby textalt="": present and empty
InformativeWhat it adds: "Ticket QR code"
The image is the buttonThe action: "Search", not "magnifying glass"
A chartA one-line summary, with the data in a table nearby

A missing alt is worse than an empty one: the reader falls back to the file name.

The numbers that make a finding

In a review, "this feels inaccessible" is an opinion. A criterion with its number is a finding. WCAG 2.2 Level A and AA are the rules products are held to:

CriterionThe rule
1.4.3 ContrastText 4.5:1; large text (24px, or 18.67px bold) 3:1
1.4.11 Non-text contrastInput borders, icons, focus rings: 3:1 against every adjacent color
1.4.1 Use of colorStatus never by color alone
2.5.8 Target size24×24px, or spaced so a 24px circle on it touches no other target
2.5.7 DraggingEvery drag has a single-click alternative
2.4.11 Focus not obscuredThe focused element is never fully hidden by sticky chrome
1.4.4 / 1.4.10Survives 200% text; works at 320px wide with vertical scroll only
2.2.2 Pause, stop, hideAnything moving or updating for more than 5 seconds has a pause
1.4.2 AudioNothing autoplays with sound

Disabled controls and logos are exempt from contrast. The 44px touch target and "one <h1> per page" are good advice but not AA, so they are recommendations, never the top severity.

Measure contrast against what the text actually sits on, not the page background.
Announcements and a WCAG check· for your agent
Audit this screen for screen-reader output and WCAG 2.2 AA:
- Pick the quietest announcement per change: focus move, aria-describedby, role="status", role="alert" (failures that block only).
- Live regions are always in the DOM and start empty; never focus a toast.
- Decorative icons aria-hidden; nothing aria-hidden contains a focusable element.
- Alt text by purpose; empty alt for decoration.
- Report each failure as: element, WCAG criterion number, measured value, threshold. Don't change colors unless I ask.

Quick check

A 'Changes saved' toast should be announced with…

What this lesson builds on and leads to, across every course.

  • Keyboard, focus and touch
  • Routing the job
  • Contrast you can read