Back

Building Accessible React Components: A Comprehensive Guide

Jun 28/8 min read
Building Accessible React Components: A Comprehensive Guide

Building Accessible React Components: A Comprehensive Guide

Accessibility isn't a feature—it's a fundamental requirement. When we build inaccessible applications, we exclude millions of users who rely on assistive technologies. Let's build better.

The Four Principles of Accessibility

1. Perceivable

Information must be presentable to users in ways they can perceive:

  • Provide text alternatives for images
  • Offer captions for videos
  • Ensure sufficient color contrast

2. Operable

Users must be able to operate the interface:

  • Make all functionality keyboard accessible
  • Give users enough time to read and interact
  • Don't design content that could cause seizures

3. Understandable

Information and operation must be understandable:

  • Make text readable and understandable
  • Make content appear and operate predictably
  • Help users avoid and correct mistakes

4. Robust

Content must be robust enough for various assistive technologies:

  • Maximize compatibility with current and future tools
  • Use valid, semantic HTML

Building Accessible Components

Semantic HTML First

Always start with semantic HTML:

// Good: Semantic button
<button onClick={handleClick}>
  Click me
</button>

// Bad: Non-semantic div
<div onClick={handleClick}>
  Click me
</div>

Keyboard Navigation

Every interactive element must be keyboard accessible:

function Dropdown() {
  const [isOpen, setIsOpen] = useState(false);

  const handleKeyDown = (e) => {
    if (e.key === 'Enter' || e.key === ' ') {
      setIsOpen(!isOpen);
    } else if (e.key === 'Escape') {
      setIsOpen(false);
    }
  };

  return (
    <div>
      <button
        onClick={() => setIsOpen(!isOpen)}
        onKeyDown={handleKeyDown}
        aria-expanded={isOpen}
        aria-haspopup="true"
      >
        Menu
      </button>
      {/* ... */}
    </div>
  );
}

ARIA Attributes

Use ARIA to enhance semantics when HTML alone isn't enough:

  • aria-label: Provides a label when visible text isn't available
  • aria-describedby: References an element that describes the current element
  • aria-live: Announces dynamic content changes
  • aria-hidden: Hides decorative elements from screen readers

Focus Management

Manage focus appropriately:

function Modal({ isOpen, onClose }) {
  const modalRef = useRef();

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

  return (
    <dialog
      ref={modalRef}
      open={isOpen}
      aria-modal="true"
      onKeyDown={(e) => {
        if (e.key === 'Escape') onClose();
      }}
    >
      {/* ... */}
    </dialog>
  );
}

Testing for Accessibility

Automated Testing

Tools like:

  • axe DevTools
  • Lighthouse
  • pa11y

Manual Testing

  • Navigate with keyboard only
  • Use a screen reader (VoiceOver, NVDA, JAWS)
  • Test with browser zoom at 200%
  • Check color contrast

Common Pitfalls

  1. Relying solely on color: Use multiple visual cues
  2. Missing alt text: Every image needs descriptive alt text
  3. Poor focus indicators: Make focus states visible
  4. Auto-playing media: Let users control playback
  5. Inaccessible forms: Label inputs properly and provide clear error messages

Conclusion

Accessibility makes the web better for everyone. It's not about checking boxes—it's about empathy and inclusive design. Start small, test often, and always keep your users in mind.

Remember: If your app isn't accessible, it's not finished.