Frontend Accessibility: ARIA, Keyboard, and Screen Readers

Accessibility is no longer optional. It is required by law in many jurisdictions and by ethics in all. Senior frontend interviews probe whether you understand the patterns — not just “alt text on images” but the deeper requirements of focus management, ARIA, and screen-reader-friendly interactions.

The four principles (POUR)

WCAG groups requirements into:

  • Perceivable: alt text, captions, sufficient contrast
  • Operable: keyboard accessible, sufficient time, no seizure-inducing content
  • Understandable: readable, predictable, helpful errors
  • Robust: works with current and future user agents (browsers, screen readers)

Semantic HTML first

The first rule of ARIA: use a semantic element if one exists. <button> beats <div role="button"> every time. Built-in elements come with:

  • Correct roles
  • Keyboard support
  • Focus styling
  • Screen reader integration

You only reach for ARIA when no semantic element fits.

ARIA core concepts

Roles

Tell assistive tech what an element is. role="dialog", role="combobox", etc. The full list is the WAI-ARIA specification.

States and properties

aria-expanded, aria-disabled, aria-pressed, aria-selected, aria-checked. Track interactive state.

Live regions

aria-live="polite" or "assertive" announces dynamic changes. Use for status messages, error notifications, search result counts.

Focus management

The most-broken accessibility area. Common situations that need explicit focus management:

  • Modal opens → focus moves into modal
  • Modal closes → focus returns to the trigger
  • Route change → focus moves to new content (not stuck on old link)
  • Form submit error → focus moves to first invalid field
  • Async load → focus moves to new content when ready

Focus trapping

Modals must trap focus. Tab cycles within the modal; Shift+Tab cycles backward. Escape closes.

Libraries handle this: focus-trap, react-focus-lock. Don’t hand-roll unless the library does not fit.

Visible focus indicators

Default browser focus rings are functional. Don’t remove them with outline: none unless you replace with a clear alternative.

Modern: :focus-visible shows focus ring only on keyboard navigation, not mouse click. Best of both.

Color contrast

WCAG AA: 4.5:1 for normal text, 3:1 for large text. WCAG AAA: 7:1.

Tools: built-in DevTools color picker shows contrast ratio. Lighthouse audits flag failures. Stark plugin for designers.

Screen reader testing

Test with at least one screen reader:

  • VoiceOver on macOS (Cmd+F5)
  • NVDA on Windows (free)
  • TalkBack on Android, VoiceOver on iOS

Hands-on testing reveals issues that automated tools cannot catch.

Common patterns

Modal

  • Trap focus
  • aria-modal=”true”, role=”dialog”
  • aria-labelledby points to title
  • Escape closes
  • Click outside closes (configurable)
  • Returns focus on close

Combobox / autocomplete

  • Input has role=”combobox”, aria-expanded, aria-controls
  • Results list has role=”listbox”
  • Active option referenced via aria-activedescendant
  • Arrow keys navigate without moving focus from input

Tabs

  • Tab list has role=”tablist”
  • Each tab has role=”tab”, aria-selected, aria-controls
  • Panel has role=”tabpanel”
  • Arrow keys move between tabs (not Tab key — Tab moves to panel content)

Automated testing

Add axe-core to your test suite:

import { axe } from 'jest-axe';

test('page has no a11y violations', async () => {
  const { container } = render(<Page />);
  expect(await axe(container)).toHaveNoViolations();
});

Catches the obvious bugs (missing labels, low contrast, invalid ARIA). Does not replace manual testing.

Common mistakes

  • Using divs for interactive elements without keyboard support
  • Removing focus rings without replacement
  • Misusing ARIA roles (role=”button” on a div without keyboard handling)
  • Live region spam (too many announcements)
  • Skipping focus management on modals
  • Placeholder as label (announces nothing useful when field is empty)

Frequently Asked Questions

Is ARIA worth learning if I use Radix or React Aria?

Yes. The libraries handle most patterns, but you will customize. Knowing the underlying ARIA matters when things go wrong.

How do I balance accessibility with custom design?

Most a11y patterns are invisible (focus management, ARIA, keyboard support). The visible aspects (focus rings, contrast) are easy to design around.

What is the legal landscape in 2026?

EU Accessibility Act (June 2025) makes accessibility a legal requirement for many products. ADA enforcement in the US continues. Lawsuits are real.

Scroll to Top