DEV Community

AgentKit
AgentKit

Posted on • Originally published at blog.a11yfix.dev

Screen Reader Testing for Developers: What VoiceOver Actually Announces (And Why It Matters)

Originally published at A11yFix.


I've been building websites for years, and I'll be honest: for most of that time, I had never actually turned on a screen reader. I assumed my HTML was "fine" because it looked right in the browser. Then I fired up VoiceOver on my Mac, navigated one of my own pages, and realized how wrong I was.

This guide is what I wish someone had handed me on day one. No theory-heavy lecture --- just practical steps to test your pages with VoiceOver and understand what users actually hear.

How to Turn On VoiceOver (It Takes 5 Seconds)

On any Mac, press Cmd + F5. That's it. VoiceOver starts talking immediately.

A few essentials before you start navigating:

  • VO keys: VoiceOver uses a modifier combination. By default, it's Control + Option (referred to as "VO" in documentation). You hold these while pressing other keys.
  • VO + Right Arrow: Move to the next element on the page.
  • VO + Left Arrow: Move to the previous element.
  • VO + Space: Activate (click) the current element.
  • VO + U: Open the rotor --- a quick menu for headings, links, landmarks, and more.
  • VO + A: Read everything from the current position forward.

Open Safari (VoiceOver works best with Safari on Mac), navigate to your site, and start pressing VO + Right Arrow to walk through the page element by element.

What to Listen For

As you navigate, pay attention to what VoiceOver actually says for each element. It typically announces:

  1. The role: "heading level 2," "link," "button," "image"
  2. The accessible name: the text content, aria-label, or alt attribute
  3. The state: "dimmed," "selected," "expanded"

A well-structured page sounds like a clear outline. A poorly structured page sounds like a random collection of text fragments with no context.

Surprise #1: Your Clickable Div Is Invisible

This is the most common shock. You have something like:

<div class="card" onclick="openDetail()">
  <h3>Premium Plan</h3>
  <p>$29/month</p>
</div>
Enter fullscreen mode Exit fullscreen mode

You click it with your mouse every day. It works perfectly. But navigate to it with VoiceOver and you hear... nothing useful. VoiceOver announces "group" or just reads the text content with no indication that this thing is interactive.

A screen reader user has no idea they can activate this element. It doesn't show up in the links or buttons list in the rotor. It's effectively invisible as an interactive element.

The fix:

<div class="card" role="button" tabindex="0"
     onclick="openDetail()"
     onkeydown="if(event.key==='Enter') openDetail()">
  <h3>Premium Plan</h3>
  <p>$29/month</p>
</div>
Enter fullscreen mode Exit fullscreen mode

Or better yet, use a real <button> and style it:

<button class="card" onclick="openDetail()">
  <h3>Premium Plan</h3>
  <p>$29/month</p>
</button>
Enter fullscreen mode Exit fullscreen mode

Now VoiceOver says "Premium Plan, $29/month, button." That's a massive difference.

Surprise #2: aria-label Overrides Your Visible Text

This one catches developers who are trying to "help" screen reader users:

<a href="/pricing" aria-label="Click here to view our pricing page">
  View Pricing
</a>
Enter fullscreen mode Exit fullscreen mode

Sighted users see "View Pricing." VoiceOver users hear "Click here to view our pricing page, link." These are different experiences, and the mismatch causes real problems.

If a sighted coworker says "click the View Pricing link," a screen reader user searching for that text won't find it. The rotor's link list will show "Click here to view our pricing page" instead.

The rule: aria-label replaces the accessible name entirely. Only use it when the visible text alone doesn't provide enough context, and try to keep it consistent with what's visible. In most cases, well-written visible text is all you need.

Surprise #3: Missing Heading Hierarchy Destroys Navigation

Screen reader users rely heavily on headings to navigate. Press VO + U and select the Headings list. This is how many users get an overview of your page.

If your heading hierarchy looks like this:

h1: Welcome
h3: Our Services    (where's h2?)
h3: About Us
h5: Contact         (jumped from h3 to h5?)
Enter fullscreen mode Exit fullscreen mode

The navigation experience is confusing. Users wonder if they're missing sections. Tools like axe will flag this, but hearing it through VoiceOver makes the problem visceral.

The fix: Use headings in order. Every page gets one h1. Sections get h2. Subsections get h3. It's not about font size --- CSS handles that. It's about document structure.

Surprise #4: Forms Without Labels Are Guessing Games

<input type="email" placeholder="Enter your email">
Enter fullscreen mode Exit fullscreen mode

VoiceOver announces: "edit text." That's it. The placeholder text might show visually, but it's not a reliable accessible name.

<label for="email">Email address</label>
<input type="email" id="email" placeholder="you@example.com">
Enter fullscreen mode Exit fullscreen mode

Now VoiceOver says: "Email address, edit text." The user knows exactly what to type.

A 10-Minute Testing Routine

Here's what I do now before shipping any feature:

  1. Cmd + F5 to start VoiceOver
  2. VO + Right Arrow through the entire new feature, listening for:
    • Can I tell what every interactive element does?
    • Do buttons and links have clear names?
    • Are images described or correctly marked as decorative?
  3. VO + U to check the headings list --- does it make sense as an outline?
  4. Tab through all interactive elements --- can I reach and activate everything?
  5. VO + Space on buttons and links --- do they work?
  6. Cmd + F5 to turn VoiceOver off

That's it. Ten minutes. You'll catch more accessibility issues in those ten minutes than in hours of staring at automated scan results.

Why This Matters More Than You Think

Starting June 2025, the European Accessibility Act requires digital products and services to be accessible. That's not a suggestion --- it's law, with real enforcement. Similar regulations are expanding worldwide.

But beyond compliance, testing with a screen reader connects you with how real people use your product. About 2.2 billion people worldwide have some form of vision impairment. When you hear VoiceOver stumble through your UI, those aren't abstract "accessibility issues" --- they're barriers.

Turn on VoiceOver today. Navigate your own site. Listen to what it actually says. I promise you'll find at least one thing that surprises you.


If you're working on accessibility compliance, I put together a free 10-point EAA quick-check: Get the free checklist

The full 100+ item checklist is also available as a printable PDF on Etsy.

Top comments (0)