React accessibility means building components that everyone can use, including people who navigate with a keyboard or a screen reader. The fastest way there is semantic HTML first, with ARIA only when a native element cannot express the behavior.
Use semantic HTML first
A native element such as a button, input, or select already has keyboard support, a role, and a name that assistive technology understands. Rebuilding that behavior on a div means writing all of it yourself and getting part of it wrong. Native elements are also more reliable than hand-built ones because browsers maintain their behavior across updates.
Use a button for actions, a link for navigation, and a form element for input. Landmarks such as main, header, and nav give screen reader users a way to jump around the page without any extra code. The same rule applies to lists and tables: use ul, ol, and table elements so their structure is announced rather than rebuilt from generic divs.
Give every control an accessible name
A form field or button needs a name that a screen reader can announce. The simplest way is a label wrapping the control.
function EmailField() {
return (
<label>
Email address
<input type="email" name="email" />
</label>
);
}The label text becomes the input's accessible name, so a screen reader announces "Email address" when the field receives focus. A placeholder is not a label, because it disappears while the user types.
Buttons get their name from their text, and an icon-only button needs an aria-label so the name is not empty. A visible label also helps sighted users, so prefer it over aria-label when space allows.
Keep focus visible and managed
Keyboard users need to see where they are. Never remove the focus outline, and keep the tab order matching the visual order.
When a modal opens, move focus into it, and when it closes, return focus to the control that opened it. A skip link at the top of the page lets keyboard users jump past repeated navigation to the main content.
The details for interactive controls are in How to Make Clickable Elements Accessible in React, and the keyboard patterns are in Keyboard Navigation Patterns for React Components.
Use headings and landmarks
Screen reader users often navigate by headings and landmarks. Use one main heading per page, keep heading levels in order, and wrap navigation in nav and main content in main.
Skipping a level, such as jumping from h1 to h3, makes the structure harder to follow. A consistent structure also helps reviewers and automated tools spot missing sections.
ARIA is the last resort
The first rule of ARIA is to use a native element when one exists. A progress bar is a good example: the native progress element already carries the role and value semantics.
function UploadProgress({ value }) {
return (
<progress aria-label="Upload progress" value={value} max={100}>
{value}%
</progress>
);
}The progress element carries the role and value automatically, but the text between the tags is only a fallback for old browsers, not an accessible name. The aria-label gives it one.
Adding a role and ARIA attributes to a div would only re-create, by hand, what the browser already provides. Incorrect ARIA is worse than no ARIA, because it misleads assistive technology.
Landmarks and native controls already expose roles, so do not duplicate them with role attributes. When a widget truly has no native equivalent, ARIA in React: When Native HTML Is Not Enough shows how to add it correctly.
Test with the keyboard
Automated checks catch missing labels and contrast problems, but the keyboard test finds the issues that matter most. Tab through the page and confirm every focusable control is reachable, visible, and operable. A tab order that matches the visual order, with a visible focus ring, is the sign the page is keyboard-friendly.
Forms deserve the same pass. A validation message must be read by a screen reader and not communicated by color alone. Run the pass before shipping, not after a complaint.
Rune AI
Key Insights
- Prefer native elements such as button and input over repurposed divs.
- Give every form control and image an accessible name or text.
- Keep focus visible and order it to match the page.
- Use ARIA only when no native element expresses the behavior.
- Test with a keyboard, not only with automated tools.
Frequently Asked Questions
Does accessibility require a lot of ARIA?
How do I know my component is accessible?
Conclusion
Accessible React starts with semantic HTML, clear accessible names, and predictable focus. Reach for ARIA only when a native element cannot express the behavior, and test with a keyboard before calling the work done.
More in this topic
How to Build a Dropdown Menu in React
Build a React dropdown menu with the ARIA menu button pattern. Handle open and close, keyboard arrows, and clicks outside the menu.
How to Animate React Components with Motion
Animate React components with the Motion library. Set up motion, add enter, hover, and exit animations, and respect reduced motion.
Headless UI Components Explained: Logic Without Locked Styling
Understand headless UI components and how libraries like Radix give you unstyled, accessible behavior that you style yourself.