This document covers the accessibility requirements and best practices for React applications as defined by the Airbnb style guide. It details the mandatory accessibility standards enforced through the eslint-plugin-jsx-a11y plugin, including image alternative text, ARIA attributes, keyboard navigation, semantic HTML usage, and form control patterns.
For general React component patterns and JSX syntax, see 3.1 React Component Structure and 3.3 JSX Formatting and Syntax For information about the ESLint configuration that enforces these rules, see 6.7 React Accessibility Rules
The Airbnb React style guide enforces accessibility as a first-class concern through approximately 40 ESLint rules configured in packages/eslint-config-airbnb/rules/react-a11y.js. These rules are implemented via the jsx-a11y plugin and are set to error severity, making accessibility violations block CI/CD pipelines packages/eslint-config-airbnb/rules/react-a11y.js1-269
The following table summarizes the major categories of accessibility rules enforced:
| Category | Description | Example Rules | Severity |
|---|---|---|---|
| Alternative Text | Images and media require descriptive text | alt-text, img-redundant-alt | Error |
| ARIA Attributes | Valid ARIA roles, properties, and states | aria-props, aria-role, aria-proptypes | Error |
| Keyboard Navigation | Interactive elements must be keyboard accessible | click-events-have-key-events, no-noninteractive-tabindex | Error |
| Semantic HTML | Proper use of HTML element semantics | heading-has-content, anchor-is-valid | Error |
| Form Controls | Labels and control associations | label-has-associated-control, control-has-associated-label | Error |
| Focus Management | Focusable elements and tab order | interactive-supports-focus, tabindex-no-positive | Error |
Sources: packages/eslint-config-airbnb/rules/react-a11y.js1-269
The following diagram shows how accessibility rules are loaded and enforced:
Sources: packages/eslint-config-airbnb/rules/react-a11y.js1-12
All images must have alternative text to ensure screen reader users can understand visual content.
The jsx-a11y/alt-text rule is configured to enforce alternative text on multiple element types packages/eslint-config-airbnb/rules/react-a11y.js21-27:
| Element | Requirement |
|---|---|
<img> | Must have alt prop |
<object> | Must have alternative text |
<area> | Must have alt prop |
<input[type="image"]> | Must have alt prop |
The jsx-a11y/img-redundant-alt rule prevents including words like "image", "photo", or "picture" in alt text packages/eslint-config-airbnb/rules/react-a11y.js115 Screen readers already announce the element type, making these words redundant.
Sources: packages/eslint-config-airbnb/rules/react-a11y.js21-27 packages/eslint-config-airbnb/rules/react-a11y.js114-115
ARIA (Accessible Rich Internet Applications) attributes enhance accessibility when semantic HTML is insufficient.
The following diagram maps ARIA-related rules to their enforcement:
The jsx-a11y/aria-role rule is configured with ignoreNonDOM: false, enforcing that only valid, non-abstract ARIA roles are used packages/eslint-config-airbnb/rules/react-a11y.js55
Three rules ensure ARIA properties are used correctly:
jsx-a11y/aria-props packages/eslint-config-airbnb/rules/react-a11y.js47 - All aria-* props must be valid ARIA property names.jsx-a11y/aria-proptypes packages/eslint-config-airbnb/rules/react-a11y.js51 - ARIA property values must match their expected types.jsx-a11y/role-has-required-aria-props packages/eslint-config-airbnb/rules/react-a11y.js224 - Elements with roles must have all required ARIA properties.Sources: packages/eslint-config-airbnb/rules/react-a11y.js43-60 packages/eslint-config-airbnb/rules/react-a11y.js224-229
All interactive functionality must be accessible via keyboard for users who cannot use a mouse.
| Rule | Purpose | Configuration |
|---|---|---|
jsx-a11y/click-events-have-key-events | Ensure onClick has keyboard equivalent | Line 70 |
jsx-a11y/mouse-events-have-key-events | Pair mouse events with keyboard events | Line 145 |
jsx-a11y/no-static-element-interactions | Prevent handlers on non-interactive elements | Lines 210-219 |
jsx-a11y/no-noninteractive-element-interactions | Block handlers on semantic non-interactive elements | Lines 169-178 |
The jsx-a11y/click-events-have-key-events rule requires that any element with an onClick handler also have onKeyUp, onKeyDown, or onKeyPress handlers packages/eslint-config-airbnb/rules/react-a11y.js70
The jsx-a11y/mouse-events-have-key-events rule ensures that onMouseOver and onMouseOut are paired with onFocus and onBlur for keyboard users packages/eslint-config-airbnb/rules/react-a11y.js145
Sources: packages/eslint-config-airbnb/rules/react-a11y.js70 packages/eslint-config-airbnb/rules/react-a11y.js145 packages/eslint-config-airbnb/rules/react-a11y.js210-219
Proper focus management ensures keyboard users can navigate through interactive elements efficiently.
jsx-a11y/tabindex-no-positive packages/eslint-config-airbnb/rules/react-a11y.js237 - Prohibits tabIndex values greater than zero, ensuring natural tab order follows DOM structure.jsx-a11y/no-noninteractive-tabindex packages/eslint-config-airbnb/rules/react-a11y.js192-196 - Prevents tabIndex on non-interactive elements, with exceptions for tabpanel role and expression values.The jsx-a11y/no-autofocus rule is configured with ignoreNonDOM: true, preventing the autoFocus prop on DOM elements while allowing it on custom components packages/eslint-config-airbnb/rules/react-a11y.js153
Sources: packages/eslint-config-airbnb/rules/react-a11y.js119 packages/eslint-config-airbnb/rules/react-a11y.js153 packages/eslint-config-airbnb/rules/react-a11y.js192-196 packages/eslint-config-airbnb/rules/react-a11y.js237
Form controls must have associated labels to ensure assistive technologies can identify their purpose.
The jsx-a11y/label-has-associated-control rule enforces comprehensive label associations packages/eslint-config-airbnb/rules/react-a11y.js123-129:
The assert: 'both' setting requires labels to be associated with controls through both nesting and ID matching.
The jsx-a11y/control-has-associated-label rule requires interactive controls to have accessible labels packages/eslint-config-airbnb/rules/react-a11y.js74-99 It ignores certain natively labeled elements like audio, canvas, and video, as well as roles like grid, listbox, and menu.
Sources: packages/eslint-config-airbnb/rules/react-a11y.js74-99 packages/eslint-config-airbnb/rules/react-a11y.js123-129
| Rule | Purpose | Configuration |
|---|---|---|
jsx-a11y/no-interactive-element-to-noninteractive-role | Prevent making interactive elements non-interactive | Lines 163-165 |
jsx-a11y/no-noninteractive-element-to-interactive-role | Prevent making non-interactive elements interactive | Lines 182-188 |
The rule jsx-a11y/no-noninteractive-element-to-interactive-role specifies allowed conversions, such as <ul> to listbox or <li> to menuitem packages/eslint-config-airbnb/rules/react-a11y.js182-188
The jsx-a11y/no-redundant-roles rule prevents specifying roles that match the element's implicit role, such as <nav role="navigation"> packages/eslint-config-airbnb/rules/react-a11y.js204-206
Sources: packages/eslint-config-airbnb/rules/react-a11y.js163-165 packages/eslint-config-airbnb/rules/react-a11y.js182-188 packages/eslint-config-airbnb/rules/react-a11y.js204-206
The jsx-a11y/no-access-key rule prohibits using the accessKey attribute, as it creates conflicts with screen reader and browser keyboard commands packages/eslint-config-airbnb/rules/react-a11y.js149
The jsx-a11y/no-distracting-elements rule prevents using elements like <marquee> and <blink> that create motion which cannot be stopped by the user packages/eslint-config-airbnb/rules/react-a11y.js157-159
Sources: packages/eslint-config-airbnb/rules/react-a11y.js149 packages/eslint-config-airbnb/rules/react-a11y.js157-159
jsx-a11y/accessible-emoji: Disabled as the rule is deprecated packages/eslint-config-airbnb/rules/react-a11y.js17jsx-a11y/label-has-for: Disabled in favor of label-has-associated-control packages/eslint-config-airbnb/rules/react-a11y.js246-252The following rules are currently disabled but marked for future major version enablement:
jsx-a11y/anchor-ambiguous-text packages/eslint-config-airbnb/rules/react-a11y.js257jsx-a11y/no-aria-hidden-on-focusable packages/eslint-config-airbnb/rules/react-a11y.js262jsx-a11y/prefer-tag-over-role packages/eslint-config-airbnb/rules/react-a11y.js267Sources: packages/eslint-config-airbnb/rules/react-a11y.js17 packages/eslint-config-airbnb/rules/react-a11y.js246-267
Refresh this wiki