Catching accessibility defects while you code

Accessibility problems are cheaper to fix when you find them during development rather than after a release. For React projects, two tools cover different stages of that process: eslint-plugin-jsx-a11y flags issues while you write JSX, and react-axe audits the final rendered DOM in the browser. In combination they give a practical safety net before production.

eslint-plugin-jsx-a11y is an ESLint plugin that enforces accessibility rules directly in your JSX. It catches structural mistakes early, such as using the wrong label attribute. React requires htmlFor in place of the standard for to correctly associate a label with a form element:

<input id="promo" type="checkbox">
<label htmlFor="promo">Receive promotional offers?</label>

react-axe, meanwhile, is a library by Deque Labs that wraps their axe-core testing engine to audit a running React application. Any violations found are logged to the Chrome DevTools console along with their severity level.

Setting up eslint-plugin-jsx-a11y

If you use Create React App (CRA), the plugin is already included. To activate its pre-configured linting rules:

  1. Install the ESLint plugin for your code editor.
  2. Add a .eslintrc.json file to your project.

{
  "extends": "react-app"
}

With that configuration in place, common accessibility defects start surfacing as you edit components.

Image accessibility warning in linter

To apply the plugin's broader set of recommended rules, change .eslintrc.json to extend the plugin's recommended configuration:

{
  "extends": ["react-app", "plugin:jsx-a11y/recommended"]
}

A stricter subset of those rules is available in the plugin's strict mode:

{
  "extends": ["react-app", "plugin:jsx-a11y/strict"]
}

Label accessibility error in linter

The project documentation covers the exact differences between the recommended and strict rule sets.

Auditing rendered output with react-axe

JSX linting never touches the final HTML. react-axe exists to fill that gap. It works by integrating the axe-core engine into a React component tree and inspecting what actually renders in the browser.

Install it as a development dependency:

On install, initialize the module in index.js, but only outside of production:

React Axe in Chrome DevTools

The dynamic import conditionally loads the library only for development builds. That keeps react-axe out of the production bundle entirely.

Once configured, running the app in development prints violations directly to the Chrome DevTools console, where each infraction carries a severity level of Minor, Moderate, Serious, or Critical.

Using both together

Make accessibility auditing part of your workflow rather than an afterthought. Use eslint-plugin-jsx-a11y for immediate inline feedback in your editor — CRA handles the base setup, and you can move to recommended or strict mode for tighter rules once your team is ready.

Overlap that with react-axe during local development so the fully assembled DOM, including runtime state changes, is inspected as well. As long as the audit library is excluded from what you ship, the cost is only a few lines added to your dev setup.