Accessibility (a11y) ensures that your React applications are usable by everyone, including people with disabilities. React makes it easier to build accessible web applications with built-in support for ARIA attributes, keyboard navigation, and screen reader compatibility.
1. Semantic HTML – The Foundation of Accessibility
Using proper HTML elements makes your app more accessible by default.
❌ Bad Example (Non-Semantic Elements)
<div onClick={() => console.log("Clicked!")}>Click me</div>
<div>
is not an interactive element.- Screen readers won’t recognize it as a button.
✅ Good Example (Using <button>
)
<button onClick={() => console.log("Clicked!")}>Click me</button>
- Keyboard & screen reader friendly by default.
- No need to manually handle focus.
Tip: Use <nav>
, <article>
, <header>
, <footer>
, <section>
, and <main>
instead of <div>
for better readability.
2. ARIA (Accessible Rich Internet Applications) Attributes
ARIA helps enhance accessibility when using non-semantic elements.
Example: ARIA for Screen Readers
<button aria-label="Close" onClick={() => console.log("Closed")}>❌</button>
aria-label="Close"
tells screen readers what the button does.
3. Managing Focus (Keyboard Navigation)
Users should be able to navigate using the keyboard (Tab, Enter, Esc).
Example: Focus on Modal Dialogs
import { useEffect, useRef } from "react"; const Modal = ({ onClose }) => { const modalRef = useRef(null); useEffect(() => { modalRef.current.focus(); // Auto-focus modal }, []); return ( <div role="dialog" tabIndex="-1" ref={modalRef} onKeyDown={(e) => e.key === "Escape" && onClose()} > <p>Press ESC to close</p> <button onClick={onClose}>Close</button> </div> ); };
tabIndex="-1"
makes the<div>
focusable.role="dialog"
tells screen readers it’s a modal.onKeyDown={(e) => e.key === "Escape" && onClose()}
allows closing via ESC key.
4 Handling Forms Accessibly
Forms should include labels, error messages, and ARIA attributes.
Example: Accessible Form
const LoginForm = () => { return ( <form> <label htmlFor="email">Email</label> <input id="email" type="email" aria-required="true" /> <button type="submit">Login</button> </form> ); };
htmlFor="email"
correctly associates the label with the input field.aria-required="true"
tells screen readers this field is mandatory.
5. Skip Links (Jump to Main Content)
For keyboard users, skip links help jump past navigation menus.
Example: Skip Navigation
<a href="#main-content" className="skip-link">Skip to main content</a> <main id="main-content"> <h1>Welcome to My Website</h1> </main>
🔹 Style .skip-link
to appear only when focused:
.skip-link { position: absolute; top: -40px; left: 0; background: #000; color: #fff; padding: 8px; } .skip-link:focus { top: 0; }
Helps screen reader & keyboard users navigate faster.
6. Alternative Text for Images
Screen readers rely on alt text to describe images.
Example: Accessible Images
<img src="profile.jpg" alt="John Doe's Profile Picture" />
- Meaningful
alt
text improves screen reader usability. - For decorative images, use
alt=""
to hide them from screen readers.
7. Color Contrast & Dark Mode
Ensure text is readable for users with low vision or color blindness.
Example: High Contrast Mode
:root { --text-color: #333; --bg-color: #fff; } @media (prefers-contrast: high) { :root { --text-color: #000; --bg-color: #f5f5f5; } }
Automatically adjusts for users with high-contrast settings.
8. Avoid onClick
Only for Interactive Elements
Some users can’t use a mouse, so always support keyboard interactions.
❌ Bad Example (No Keyboard Support)
<div onClick={() => console.log("Clicked!")}>Click me</div>
Keyboard users can’t “click” this div!
✅ Good Example (Keyboard Accessible)
<div role="button" tabIndex="0" onClick={() => console.log("Clicked!")} onKeyDown={(e) => e.key === "Enter" && console.log("Clicked!")} > Click me </div>
tabIndex="0"
makes it focusable.onKeyDown
enables Enter key interaction.
9. Accessible Tables
Tables should include headers and descriptions for clarity.
Example: Proper Table Markup
<table> <caption>Monthly Sales Report</caption> <thead> <tr> <th scope="col">Month</th> <th scope="col">Sales</th> </tr> </thead> <tbody> <tr> <td>January</td> <td>$10,000</td> </tr> </tbody> </table>
<caption>
provides a table summary.<th scope="col">
properly defines column headers.
10. Testing Accessibility (a11y)
Use Browser DevTools
- Chrome: Right-click → Inspect → Lighthouse → Accessibility Audit.
- Firefox: Inspect → Accessibility Panel.
Use Screen Readers
- Windows: NVDA (free)
- Mac: VoiceOver (built-in)
- Chrome: ChromeVox (extension)
Automated Testing Tools
- 🛠️ axe DevTools (Chrome extension)
- 🛠️ react-a11y (npm package)
🔹 Summary – React Accessibility Checklist
- Use semantic HTML (avoid
div
for buttons) - Add ARIA attributes when necessary
- Ensure keyboard navigation (focus, ESC to close modals)
- Provide labels & error messages for forms
- Use skip links for navigation
- Add alt text for images
- Ensure high contrast for better readability
- Support keyboard & mouse interactions
- Use accessible tables for data
- Test with Lighthouse, screen readers, and a11y tools