Screen Readers & Live Regions
A screen reader is software that converts on-screen content into synthesized speech or braille output. Understanding roughly how it parses your HTML—and testing with a real one occasionally—is one of the highest-leverage accessibility skills you can build, because it exposes gaps that a purely visual review never will.
How Screen Readers Parse a Page
The HTML element itself (a <button> has an implicit role of "button").
Its accessible name (visible text, alt text, aria-label, or a linked <label>).
Its state (checked, expanded, disabled, invalid, current focus).
Its position in the document, including landmarks and heading levels.
<nav> is announced as a navigation landmark; an <h2> is announced as "heading level 2." A generic <div> announces nothing at all unless you add ARIA to compensate.what-gets-announced.html
<nav aria-label="Primary">
<ul>
<li><a href="/">Home</a></li>
<li><a href="/docs">Docs</a></li>
</ul>
</nav>
<!-- Announced roughly as: -->
<!-- "Primary, navigation landmark" -->
<!-- "list, 2 items" -->
<!-- "Home, link, 1 of 2" -->Navigating by Headings and Landmarks
<header>, <nav>, <main>, <aside>, <footer>) to get a mental map of the page before deciding where to dive in. A correct, unbroken heading hierarchy isn't a nicety—it's primary navigation infrastructure for these users.A Quick Testing Workflow
You don't need to become a screen-reader power user to catch the most common problems—a five-minute pass with the tool built into your OS surfaces most of them.
Platform | Screen reader | How to start it |
|---|---|---|
macOS | VoiceOver | Cmd + F5 (or Cmd + triple-tap Touch ID) |
Windows | NVDA (free) | Download from nvaccess.org, then Ctrl + Alt + N |
Windows | Narrator (built-in) | Ctrl + Win + Enter |
iOS | VoiceOver | Settings → Accessibility → VoiceOver |
Android | TalkBack | Settings → Accessibility → TalkBack |
A minimal manual test you can run on any page:
Turn on VoiceOver or NVDA and close your eyes (or turn off the monitor).
Tab through every interactive element—can you tell what each one does?
Jump heading to heading—does the outline make sense out of context?
Submit a form with an error—does the screen reader announce what went wrong?
Live Regions: Announcing Dynamic Changes
aria-live is for.aria-live-basic.html
<div aria-live="polite" id="cart-status"></div>
<script>
document.getElementById('cart-status').textContent =
'3 items added to cart';
</script>aria-live region changes, the screen reader announces the new content automatically—no focus change required.Value | Behavior |
|---|---|
aria-live="polite" | Announces when the user is idle; does not interrupt current speech. Use for most status updates. |
aria-live="assertive" | Interrupts immediately. Reserve for urgent, time-sensitive messages like a session timeout. |
aria-live="off" | Default for most elements; changes are not announced. |
aria-live="assertive" talks over whatever the user is currently doing. Reach for polite by default and reserve assertive for genuinely urgent messages.aria-live behavior without you setting the attribute directly:role-status-alert.html
<!-- role="status" behaves like aria-live="polite" --> <div role="status">Saved successfully.</div> <!-- role="alert" behaves like aria-live="assertive" --> <div role="alert">Error: connection lost.</div>
aria-live region if it was already present in the DOM when the page loaded. Injecting a brand-new aria-live element and its text at the same time is unreliable—render the empty container up front, then fill it in later.Visually-Hidden Text for Screen Readers Only
Sometimes you need to give a screen reader more context than a sighted user needs on screen—like clarifying that an icon-only button closes a dialog. The standard technique is a "visually-hidden" CSS class: content stays in the accessibility tree but is clipped from the visual layout.
visually-hidden.css
.visually-hidden {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}visually-hidden-usage.html
<button type="button"> <svg aria-hidden="true"><!-- close icon --></svg> <span class="visually-hidden">Close dialog</span> </button>
display: none and visibility: hidden remove content from the accessibility tree too—screen readers skip it entirely. Use the clip-based visually-hidden pattern above instead, which hides content visually while keeping it announced.Quick Reference
Concept | Use it for |
|---|---|
Accessible name | What gets spoken to identify an element |
Heading navigation | Jumping between sections of a page |
Landmark regions | Getting an overview of the page layout |
aria-live="polite" | Non-urgent status updates |
aria-live="assertive" | Urgent, interrupting announcements |
role="status" / role="alert" | Shorthand for the two live-region types above |
.visually-hidden | Extra context for screen readers, hidden visually |