Ignoring Accessibility Best Practices in JSX
The Critical Importance of Web Accessibility
Overlooking accessibility in React components creates barriers for:
- Screen reader users
- Keyboard-only navigators
- Users with motor impairments
- People with cognitive disabilities
- Low-vision users
Common Accessibility Oversights in JSX
1. Missing Alt Text for Images
// ❌ No alt text - screen readers can't interpret
<img src="logo.png" />
// ✅ Properly accessible
<img
src="logo.png"
alt="Company logo - Acme Inc."
width="120"
height="40"
/>
2. Non-Semantic HTML Structure
// ❌ Div soup with no semantic meaning
<div onClick={handleClick}>Read More</div>
// ✅ Proper semantic button
<button
onClick={handleClick}
aria-label="Read more about our services"
>
Read More
</button>
3. Missing ARIA Attributes
// ❌ No indication of button state
<button className={isActive ? 'active' : ''}>
// ✅ Proper ARIA attributes
<button
aria-pressed={isActive}
aria-expanded={isExpanded}
>
4. Poor Focus Management
// ❌ No focus handling for modals
function Modal() {
return <div className="modal">...</div>;
}
// ✅ Proper focus trapping
function Modal() {
const modalRef = useRef(null);
useEffect(() => {
const focusable = modalRef.current.querySelectorAll('button, [href], input');
focusable[0]?.focus();
}, []);
return <div ref={modalRef} role="dialog" aria-modal="true">...</div>;
}
Comprehensive Accessibility Solutions
Image Accessibility
// Decorative images should have empty alt
<img
src="divider.png"
alt=""
role="presentation"
/>
// Complex images need detailed descriptions
<img
src="chart.png"
alt="Bar chart showing Q3 sales growth: Product A increased 15%, Product B decreased 3%"
longdesc="#chart-data"
/>
Form Accessibility
<>
<label htmlFor="email-input">Email address</label>
<input
id="email-input"
type="email"
aria-required="true"
aria-invalid={hasError}
aria-describedby="email-error"
/>
{hasError && (
<span id="email-error" role="alert">
Please enter a valid email address
</span>
)}
</>
Interactive Element Best Practices
// Toggle buttons
<button
aria-label="Dark mode toggle"
aria-pressed={isDarkMode}
onClick={toggleTheme}
>
{isDarkMode ? '🌙' : '☀️'}
</button>
// Disabled buttons
<button
disabled={isLoading}
aria-disabled={isLoading}
aria-busy={isLoading}
>
{isLoading ? 'Processing...' : 'Submit'}
</button>
Essential Tools for Accessibility Testing
- Screen Readers:
- NVDA (Windows)
- VoiceOver (Mac/iOS)
- JAWS (Windows)
- Browser Tools:
- Accessibility inspector in Chrome DevTools
- Firefox Accessibility Panel
- Automated Testing:
- eslint-plugin-jsx-a11y
- Axe DevTools
- Lighthouse audits
- Keyboard Testing:
- Tab through all interactive elements
- Check focus visibility
- Verify logical tab order
Key Accessibility Principles to Remember
- Perceivable – Content available to all senses
- Operable – Interface works with keyboard/voice
- Understandable – Clear content and operation
- Robust – Works across browsers/assistive tech