Frontendlab
ReactAccessibility

Building Accessible React Components

Dec 15, 2024
By Michael Johnson
8 min read

Creating accessible components isn't just about compliance—it's about building better user experiences for everyone. In this article, we'll explore practical techniques for building React components that are both beautiful and accessible.

Why Accessibility Matters

Web accessibility ensures that people with disabilities can perceive, understand, navigate, and interact with websites and tools. For React developers, this means creating components that work with assistive technologies and can be used by keyboard-only users.

Beyond the ethical considerations, there are practical reasons to prioritize accessibility:

  • It expands your user base
  • It improves SEO
  • It's often a legal requirement
  • It leads to better overall UX for all users

Key Principles for Accessible Components

When building React components, keep these principles in mind:

1. Semantic HTML

Always start with the most appropriate HTML element for the job. React makes it easy to forget that we're still building with HTML, but the right semantic elements provide built-in accessibility features.

// Bad
<div onClick={handleClick}>Click me</div>

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

2. Keyboard Navigation

Ensure all interactive elements can be accessed and operated using only a keyboard. This includes focus management, which is especially important in SPAs.

Pro tip: Try navigating your application using only the Tab, Enter, and arrow keys. If you can't access all interactive elements or if the focus order is confusing, you have work to do.

3. ARIA Attributes

When HTML semantics aren't enough, ARIA attributes can provide additional context to assistive technologies. However, use them judiciously—no ARIA is better than bad ARIA.

<button
  aria-expanded={isOpen}
  aria-controls="dropdown-menu"
  onClick={toggleMenu}
>
  Menu
</button>
<div id="dropdown-menu" hidden={!isOpen}>
  {/* Menu items */}
</div>

Building an Accessible Dropdown

Let's put these principles into practice by building an accessible dropdown component:

import React, { useState, useRef, useEffect } from 'react';

function Dropdown({ label, items }) {
  const [isOpen, setIsOpen] = useState(false);
  const dropdownRef = useRef(null);

  // Close dropdown when clicking outside
  useEffect(() => {
    function handleClickOutside(event) {
      if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
        setIsOpen(false);
      }
    }
    
    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, []);

  // Handle keyboard navigation
  function handleKeyDown(event) {
    switch (event.key) {
      case 'Escape':
        setIsOpen(false);
        break;
      case 'ArrowDown':
        if (isOpen) {
          // Focus first item
          event.preventDefault();
          const firstItem = dropdownRef.current.querySelector('li button');
          firstItem?.focus();
        }
        break;
      default:
        break;
    }
  }

  return (
    <div ref={dropdownRef} onKeyDown={handleKeyDown}>
      <button
        aria-haspopup="true"
        aria-expanded={isOpen}
        onClick={() => setIsOpen(!isOpen)}
      >
        {label}
      </button>
      
      {isOpen && (
        <ul role="menu">
          {items.map((item, index) => (
            <li key={index} role="none">
              <button role="menuitem">{item}</button>
            </li>
          ))}
        </ul>
      )}
    </div>
  );
}

This component includes several accessibility features:

  • Proper ARIA attributes to indicate the dropdown behavior
  • Keyboard support for opening, navigating, and closing the dropdown
  • Click-outside behavior to close the dropdown
  • Semantic HTML with appropriate roles

"Accessibility is not a feature. It's a quality requirement that applies to every feature."

— Heydon Pickering, Inclusive Design Patterns

Testing for Accessibility

Building accessible components is only half the battle—you also need to test them. Here are some tools that can help:

  • React Testing Library: Encourages accessible testing practices
  • axe-core: Automated accessibility testing
  • Keyboard navigation testing: Try using your components without a mouse
  • Screen reader testing: NVDA (Windows) or VoiceOver (Mac)
Screenshot of accessibility testing tools in action

Using axe DevTools to identify accessibility issues in a React component

Common Accessibility Mistakes

Even with the best intentions, it's easy to make accessibility mistakes. Here are some common pitfalls to avoid:

MistakeBetter Approach
Using divs for buttonsUse the <button> element
Missing form labelsAlways associate labels with form controls
Poor color contrastEnsure text meets WCAG contrast guidelines
Relying on color aloneUse additional indicators like icons or patterns

Conclusion

Building accessible React components requires attention to detail and a commitment to inclusive design principles. By starting with semantic HTML, managing focus, using ARIA attributes appropriately, and testing thoroughly, you can create components that work for everyone.

Remember that accessibility is not a checkbox to tick off—it's an ongoing process of learning and improvement. The extra effort pays off in the form of a better experience for all users, regardless of their abilities or how they access your application.

MJ

Michael Johnson

Frontend developer specializing in React and accessibility. Passionate about creating inclusive web experiences and teaching others to do the same.

Related Articles

React

Optimizing React Performance

Deep dive into React performance optimization techniques including memoization, code splitting, and bundle analysis.

Dec 8, 2024 • 12 min read
CSS

CSS Custom Properties in Practice

Master CSS custom properties (variables) to create maintainable stylesheets and dynamic theming systems.

Dec 5, 2024 • 7 min read

Comments

TS
Taylor Smith
3 days ago

Great article! I've been struggling with making my dropdowns accessible. The example code is really helpful. Do you have any recommendations for handling focus when a modal opens?

RJ
Robin Jones
5 days ago

I appreciate the emphasis on semantic HTML. Too often we reach for divs and spans when there are better elements available. Would love to see a follow-up article on accessible forms!

Add a comment

Frontendlab