Tags: ux web-dev concept

Screen Readers

Date: 2026-08-17


Software that reads an interface aloud, navigating by its structure. Most of what makes a site work with one is using the right HTML element — and most of what breaks it is ARIA added to markup that didn’t need it.


A screen reader converts the interface into speech or braille, letting a user navigate by structure — headings, landmarks, links, form controls — rather than by looking.

It reads the accessibility tree, not the visual page — a parallel structure the browser derives from your markup — The Accessibility Tree.

How people actually navigate

The most important thing to understand, because it changes what matters:

NOT top-to-bottom, word by word

INSTEAD
  jump between HEADINGS
    → "list of 14 headings"
  jump between LANDMARKS
    → nav, main, footer
  jump between LINKS
    → "list of all links"
  jump between FORM CONTROLS
  read the current element

Heading structure is navigation. A page with one <h1> and no other headings offers no way to skim — the user must read linearly or leave.

Link text out of context is a list. “Click here” repeated eleven times is eleven identical entries in the links list. Link text must make sense alone — Microcopy.

The readers in use

NVDA        Windows, free, widely used
JAWS        Windows, commercial,
            common in enterprise
VoiceOver   macOS and iOS, built in
TalkBack    Android, built in
Narrator    Windows, built in

Behaviour differs between them, and between browser pairings. Something working in VoiceOver/Safari may not in NVDA/Firefox — which is why testing on one is a start rather than a conclusion.

[CHECK: current screen reader usage-share surveys before citing specific proportions — these are published periodically and shift.]

What breaks it

DIVS AS BUTTONS
  <div onclick>  → no role, not
                   focusable, no keyboard
                   → invisible as a control

MISSING LABELS
  an input with only a placeholder
  → announced as "edit text, blank"

IMAGES WITHOUT ALT
  → the filename is read out

HEADING LEVELS SKIPPED OR VISUAL
  <h4> used because it looked right
  → the structure lies

DYNAMIC UPDATES, SILENT
  the basket count changes, nothing
  is announced
  → Feedback and System Status

FOCUS NOT MANAGED
  a modal opens, focus stays behind it
  → Focus Management

ARIA ADDED TO WORKING HTML
  role="button" on a <button>
  → redundant at best

See: Feedback and System Status · Focus Management

The first rule of ARIA

No ARIA is better than bad ARIA.

<!-- correct: nothing needed -->
<button>Add to basket</button>
 
<!-- an accurate reimplementation -->
<div role="button" tabindex="0"
     onclick="add()" onkeydown="…">
  Add to basket
</div>
 
<!-- broken: role without behaviour -->
<div role="button" onclick="add()">
  Add to basket
</div>

The third is worse than a plain div, because it announces itself as a button and then doesn’t behave like one. The native element brings the role, focusability, keyboard handling and state for free — Semantic HTML.

Announcing dynamic changes

<div aria-live="polite">
  Added to basket. 3 items.
</div>
aria-live="polite"      announced when
                        the user pauses
aria-live="assertive"   interrupts
                        → errors only
role="status"           polite, built in
role="alert"            assertive, built in

The region must exist in the DOM before the content changes. Inserting a live region and its message simultaneously frequently announces nothing — a common and confusing bug.

Testing without expertise

You don’t need fluency to find the big problems:

1  turn on VoiceOver (Cmd+F5) or NVDA
2  close your eyes, or turn off the
   monitor
3  attempt to buy something
4  note every point you're stuck or
   confused

An hour of this finds more than any automated scan, and the failures are unambiguous — you either completed the purchase or you didn’t — WCAG.

Screen reader users are experts at their tool. Your fumbling isn’t representative of their speed — but a barrier that stops you will stop them too.