Estimated reading time: 8 minutes By: Editorial Team Published: February 5, 2024

Overview

Accessibility is not a checklist to complete before launch — it is a design constraint that produces better interfaces for everyone. Keyboards, screen readers, and cognitive aids are used by millions of people, and the patterns that serve them also improve usability for sighted users on touchscreens, noisy environments, and unfamiliar devices.

Key takeaways

  • Semantic HTML provides most accessibility for free; ARIA should extend it, not replace it.
  • Focus management is the single most common accessibility gap in JavaScript-heavy applications.
  • Color contrast and label clarity benefit all users, not only those with disabilities.
  • Automated testing catches roughly 30–40% of accessibility issues; manual testing covers the rest.

Semantic HTML first

Browsers expose native HTML elements to assistive technology with built-in roles, states, and keyboard behavior. A <button> is focusable, activatable with Enter and Space, and announced as a button by screen readers automatically.

Replacing semantic elements with styled <div> tags requires manually recreating all of this behavior — which is never done completely:

<!-- Bad: requires manual role, tabindex, keyboard handler, focus style -->
<div class="btn" onclick="submit()">Submit</div>

<!-- Good: keyboard, focus, and announcement come free -->
<button type="submit">Submit</button>

Use semantic landmarks (<nav>, <main>, <aside>, <footer>) to give screen reader users a navigable page structure. Users of NVDA and JAWS navigate by landmark far more often than sighted users realize.

Focus management

Focus management is the practice of explicitly placing keyboard focus in the right place as the UI changes. It is essential for modal dialogs, dynamic content, and single-page navigation.

Modal dialogs

When a modal opens:

  1. Move focus to the first interactive element inside the modal (or the modal container if there are none)
  2. Trap focus within the modal — Tab and Shift+Tab should cycle through the modal's interactive elements only
  3. When the modal closes, return focus to the element that triggered it
// Minimal focus trap
modal.addEventListener("keydown", (e) => {
	if (e.key !== "Tab") return;
	const focusable = modal.querySelectorAll(
		'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
	);
	const first = focusable[0];
	const last = focusable[focusable.length - 1];
	if (e.shiftKey && document.activeElement === first) {
		last.focus();
		e.preventDefault();
	} else if (!e.shiftKey && document.activeElement === last) {
		first.focus();
		e.preventDefault();
	}
});

Page navigation in SPAs

When navigating between routes in a single-page application, focus does not move automatically the way it does on a full page load. Move focus to the page's <h1> or a skip-link target after each navigation to signal the change to screen reader users.

Form patterns

Forms are where most accessibility failures are felt most acutely, because errors block task completion.

Labels and instructions

Every input needs a visible label associated with the for/id attribute pair — not a placeholder, which disappears on focus and provides no label for screen readers.

<!-- Bad: placeholder-only -->
<input type="email" placeholder="Email address" />

<!-- Good: explicit label -->
<label for="email">Email address</label>
<input id="email" type="email" autocomplete="email" />

Instructions that apply to a field before submission (character limits, format requirements) should appear in the label or in a <p> linked via aria-describedby, not only as post-submission errors.

Error messages

Error messages must be programmatically associated with their field and announced immediately:

<label for="email">Email address</label>
<input
	id="email"
	type="email"
	aria-describedby="email-error"
	aria-invalid="true" />
<p id="email-error" role="alert">Enter a valid email address.</p>

The role="alert" causes the message to be announced by screen readers when it is injected into the DOM. Setting aria-invalid="true" on the input flags it in the accessibility tree.

Color and contrast

WCAG 2.2 requires a contrast ratio of at least 4.5:1 for normal text and 3:1 for large text (18pt regular or 14pt bold). These thresholds serve users with low vision, but they also improve readability in bright sunlight, on low-quality displays, and for aging users whose contrast sensitivity decreases over time.

Do not communicate information using color alone — always pair color with a second signal (an icon, a label, a pattern).

Navigation patterns

Skip navigation

A "skip to main content" link at the top of every page allows keyboard users to bypass repeated navigation. It can be visually hidden until it receives focus:

<a href="#main" class="sr-only focus:not-sr-only">Skip to main content</a>

Keyboard-accessible dropdowns

Navigation menus with dropdowns must be fully operable by keyboard:

  • Arrow keys move between items within the dropdown
  • Escape closes the dropdown and returns focus to the trigger
  • Tab moves to the next top-level item, closing the open dropdown

Testing accessibility

Automated tools catch roughly 30–40% of WCAG failures reliably. The remainder require manual testing.

Automated tools

  • axe DevTools browser extension — high signal-to-noise, integrated with most CI pipelines
  • Lighthouse accessibility audit — scores pages and highlights issues
  • eslint-plugin-jsx-a11y — catches common issues in JSX at write time

Manual testing checklist

  • [ ] Navigate the entire page using only a keyboard (Tab, Shift+Tab, Enter, Space, arrow keys)
  • [ ] Test with VoiceOver (macOS/iOS) or NVDA (Windows) — confirm that all interactive elements are announced correctly
  • [ ] Check that focus is always visible and never lost
  • [ ] Zoom to 200% — confirm layout does not break and content remains readable
  • [ ] Confirm that all form errors are announced and associated with their fields

Conclusion

Accessible interfaces are not harder to build — they require different habits. Semantic HTML, explicit labels, focus management, and contrast-aware design produce interfaces that work for more people and perform better across the wide variety of devices and conditions your users actually encounter.

More resources