Accessibility in React
โš›๏ธ React 18+ ๐ŸŸข Chapter 32 of 39 ๐Ÿ“‚ Phase 14: Accessibility and UI Quality ๐Ÿ“… 2026 Edition
๐Ÿ“Œ Covered in this chapter: Semantic HTML ยท Labels for Inputs ยท Keyboard Navigation ยท Focus Management ยท ARIA Basics ยท Accessible Buttons & Modals ยท Color Contrast
Accessibility (often shortened to "a11y") means building UI that works for everyone, including people using screen readers, keyboard-only navigation, or who have visual impairments. React doesn't handle this automatically โ€” it's a set of practices you apply deliberately.
1Semantic HTML as the Foundation
// โŒ A div pretending to be a button gives screen readers and keyboard users nothing to work with
<div onClick={handleClick}>Submit</div>

// โœ… A real button is focusable, keyboard-operable, and announced correctly by screen readers automatically
<button onClick={handleClick}>Submit</button>

The single highest-impact accessibility practice is simply using the correct native HTML element for the job โ€” <button> for actions, <nav> for navigation, <main> for primary content โ€” rather than generic <div>s with click handlers attached. Browsers and assistive technology already understand these elements' roles for free.

2Labels for Form Inputs
๐Ÿ’ป Example 1: Properly Labeled Form Fields
function LoginForm() {
  return (
    <form>
      <label htmlFor="email">Email Address</label>
      <input id="email" type="email" />

      <button type="submit">Log In</button>
    </form>
  );
}

Connecting a <label> to its input via matching htmlFor / id attributes lets screen readers announce what each field is for, and lets users click the label text itself to focus the input โ€” a form with only placeholder text and no real labels is a very common, easily fixed accessibility failure.

3ARIA Attributes and Accessible Modals
function Modal({ isOpen, onClose, children }) {
  if (!isOpen) return null;

  return (
    <div
      role="dialog"
      aria-modal="true"
      aria-labelledby="modal-title"
    >
      <h2 id="modal-title">Confirm Action</h2>
      {children}
      <button onClick={onClose} aria-label="Close dialog">โœ•</button>
    </div>
  );
}

ARIA (Accessible Rich Internet Applications) attributes fill gaps HTML alone can't express โ€” role="dialog" and aria-modal="true" tell assistive technology this <div> behaves like a modal window, and aria-label gives an icon-only button (โœ•) a meaningful name for screen readers, since there's no visible text to announce otherwise.

4Focus Management and Color Contrast
import { useRef, useEffect } from "react";

function Modal({ isOpen }) {
  const closeButtonRef = useRef(null);

  useEffect(() => {
    if (isOpen) closeButtonRef.current?.focus();
  }, [isOpen]);

  return <button ref={closeButtonRef}>Close</button>;
}

When a modal opens, moving keyboard focus into it (using useRef, from Chapter 20) is essential for keyboard-only users, who would otherwise have no idea the modal even appeared. Separately, ensure sufficient color contrast between text and its background โ€” light gray text on a white background may look elegant but is genuinely unreadable for many users with low vision.

โš ๏ธ Removing Focus Outlines with CSS for Aesthetic Reasons

Adding outline: none to buttons and links because the default focus ring "looks ugly" removes the only visual indicator keyboard users have for where they currently are on the page. If you want a custom focus style, replace it with an equally visible alternative โ€” never remove it entirely.

๐Ÿ’ป Hands-on Interactive Practice Challenge

Build a simple accessible form with a properly connected label and input, and a submit button that uses a real

โ“ Frequently Asked Questions (FAQ)

Q Do I need to add ARIA attributes to every element?

No โ€” the general rule is 'no ARIA is better than bad ARIA.' Use semantic HTML elements first, since they come with correct accessibility behavior built in, and reach for ARIA attributes only to fill genuine gaps, like the custom modal example above.

Q How can I test if my React app is accessible?

Browser extensions like axe DevTools or Lighthouse (built into Chrome DevTools) automatically scan a page for common accessibility issues. Beyond automated tools, actually navigating your app using only the keyboard (Tab, Enter, Escape) reveals problems tools alone often miss.

OC
Written by Our Compiler Technical Editorial Team
Reviewed for accuracy & tested on React 18+ ยท Last updated August 2026