Skip to content
intermediatePhase 39 · Accessibility

Screen Readers

Build content that works with screen readers and assistive technology.

45m
0 problems
Topic Progress0%

How Screen Readers Work

How Screen Readers Work

Screen readers convert content to speech or braille.

Screen Reader Types

Screen Reader Platform Cost
NVDA Windows Free
JAWS Windows Paid
VoiceOver macOS/iOS Free
TalkBack Android Free
Narrator Windows Built-in

How They Parse Content

  1. Document structure: Headings, landmarks, lists
  2. Semantic elements: Buttons, links, forms
  3. ARIA attributes: Roles, states, properties
  4. Text content: Labels, descriptions
  5. Relationships: Labels, descriptions

Common Screen Reader Issues

// ❌ Image without alt text
<img src="photo.jpg" />

// ✅ Image with alt text
<img src="photo.jpg" alt="Team meeting in conference room" />

// ❌ Icon without label
<button><Icon /></button>

// ✅ Icon with label
<button aria-label="Close dialog"><Icon /></button>

// ❌ Dynamic content without live region
<div>{statusMessage}</div>

// ✅ Dynamic content with live region
<div aria-live="polite">{statusMessage}</div>

Reading Order

// Reading order follows DOM order
function Layout() {
  return (
    <div>
      <header>Header</header>
      <main>Main Content</main>
      <aside>Sidebar</aside>
      <footer>Footer</footer>
    </div>
  );
  // Screen reader reads: Header → Main Content → Sidebar → Footer
}

Live Regions

Live Regions

Announce dynamic content changes to screen readers.

Live Region Types

// Polite: Waits for user to finish
<div aria-live="polite">
  {results.length} results found
</div>

// Assertive: Interrupts immediately
<div aria-live="assertive">
  {errorMessage}
</div>

// Off: No announcement
<div aria-live="off">
  {debugInfo}
</div>

Status Updates

function SearchResults({ query, results, isLoading }) {
  return (
    <div>
      <input type="search" value={query} aria-label="Search" />
      
      {/* Status announcement */}
      <div aria-live="polite" className="sr-only">
        {isLoading
          ? 'Loading results...'
          : `${results.length} results for "${query}"`
        }
      </div>
      
      {/* Visible results */}
      <ul>
        {results.map(result => (
          <li key={result.id}>{result.title}</li>
        ))}
      </ul>
    </div>
  );
}

Error Announcements

function Form() {
  const [errors, setErrors] = useState({});

  return (
    <form>
      {/* Error summary for screen readers */}
      {Object.keys(errors).length > 0 && (
        <div role="alert" aria-live="assertive">
          <h2>Please fix the following errors:</h2>
          <ul>
            {Object.entries(errors).map(([field, error]) => (
              <li key={field}>{error}</li>
            ))}
          </ul>
        </div>
      )}
      
      {/* Form fields */}
    </form>
  );
}

Timer Updates

function Countdown({ seconds }) {
  return (
    <div>
      {/* Don't announce every second */}
      <div aria-live="off" aria-atomic="true">
        {formatTime(seconds)}
      </div>
      
      {/* Announce when done */}
      {seconds === 0 && (
        <div role="status" aria-live="assertive">
          Time's up!
        </div>
      )}
    </div>
  );
}

Best Practices

  1. Use politely for non-urgent updates
  2. Use assertively only for errors
  3. Don't overuse live regions
  4. Keep announcements concise
  5. Test with screen readers

Testing with Screen Readers

Testing with Screen Readers

Manual Testing

NVDA (Windows):

  1. Download from nvaccess.org
  2. Browse mode: Navigate with arrow keys
  3. Focus mode: Interact with forms
  4. Shortcut: Insert + Space to toggle modes

VoiceOver (macOS):

  1. Enable: Cmd + F5
  2. Navigate: VO + Arrow keys
  3. Interact: VO + Space
  4. Rotor: VO + U for navigation

Testing Checklist

  • All images have meaningful alt text
  • Headings create logical outline
  • Form inputs have labels
  • Errors are announced
  • Interactive elements are keyboard accessible
  • Focus order is logical
  • Dynamic content is announced

Automated Testing

// axe-core testing
import { axe, toHaveNoViolations } from 'jest-axe';

describe('Accessibility', () => {
  it('should have no violations', async () => {
    const { container } = render(<MyComponent />);
    const results = await axe(container);
    expect(results).toHaveNoViolations();
  });
});
// Playwright screen reader testing
const { test, expect } = require('@playwright/test');

test('screen reader announcement', async ({ page }) => {
  await page.goto('/');
  
  // Check for aria-live region
  const liveRegion = page.locator('[aria-live="polite"]');
  await expect(liveRegion).toBeAttached();
  
  // Perform action
  await page.click('button');
  
  // Check announcement
  await expect(liveRegion).toContainText('Action completed');
});

Common Issues

Issue Impact Fix
Missing alt text Can't understand images Add meaningful alt
No heading structure Can't navigate Use h1-h6 properly
Missing labels Can't identify inputs Add labels or aria-label
No focus indicator Can't see focus Add visible focus styles
Dynamic content silent Miss updates Use aria-live

Practice Problems

0/3solved
Build Screen Readers Component

Create a reusable React component implementing Screen Readers. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
Screen Readers Testing

Write unit and integration tests for Screen Readers using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
Screen Readers Performance

Optimize Screen Readers for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. What is the difference between aria-live="polite" and "assertive"?

Question 1 options

2. Which screen reader is free for Windows?

Question 2 options

3. What is the primary purpose of Screen Readers?

Question 3 options

4. What is a common mistake when implementing Screen Readers?

Question 4 options

Flashcards

Question

What are live regions?

Answer

ARIA attributes that announce dynamic content changes to screen readers.

Question

When should you use aria-live="assertive"?

Answer

Only for urgent errors or messages that need immediate attention.

Question

How do screen readers navigate?

Answer

By headings, landmarks, links, and form controls in the DOM order.

Question

What is the sr-only class?

Answer

A CSS class that hides content visually but keeps it available to screen readers.

Question

What is Screen Readers?

Answer

Screen Readers is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.Screen readers convert content to speech or braille
  • 2.Use aria-live for dynamic content updates
  • 3.Test with actual screen readers, not just automated tools
  • 4.Follow DOM order for reading order
  • 5.Use sr-only class for screen reader only content

Interview Tips

  • Explain how screen readers work
  • Discuss live regions and when to use them
  • Know how to test accessibility with screen readers

Cheat Sheet

Screen Readers Cheat Sheet

Live Regions

  • polite: Wait for user
  • assertive: Interrupt
  • off: No announcement

Testing

  • NVDA: Free, Windows
  • VoiceOver: Free, macOS
  • Keyboard navigation

Common Issues

  • Missing alt text
  • No heading structure
  • Missing form labels
  • No focus indicator
  • Silent dynamic content