Audit accessibilité React : RGAA 4.1.2 en 30 secondes
Une application React n'est pas accessible par défaut. Le DOM virtuel ne change rien aux règles du RGAA 4.1.2 : il faut des éléments sémantiques, des ARIA corrects, une gestion de focus pensée et des routes annoncées. Ce guide couvre les outils et patterns à maîtriser en 2026.
React, RGAA et SPA en 2026
Une application React n'est pas accessible par défaut. Le DOM virtuel ne change rien aux règles du RGAA 4.1.2 : il faut des éléments sémantiques, des ARIA corrects, une gestion de focus pensée et des routes annoncées. React 19 (stable depuis décembre 2024) apporte useId, les Server Components et les Form Actions qui aident sur la traçabilité ARIA et la cohérence SSR. Mais l'accessibilité reste portée par les patterns que vos équipes appliquent et par les bibliothèques que vous choisissez (React Aria, Base UI, Radix).
Décembre 2024
Sortie React 19 stable
35+
Composants Base UI 1.0 (MUI, fév. 2026)
106
Critères RGAA 4.1.2
En Bref : L'essentiel à retenir
- Framework : React nécessite une attention particulière à la sémantique HTML.
- Point Critique : Gestion du focus lors de la navigation dynamique.
- Outil Recommandé : eslint-plugin-jsx-a11y.
- Critères RGAA clés : 7.1, 7.3, 8.9.
Versions React et accessibilité
| Version | Support | Fonctionnalités A11y |
|---|---|---|
| React 17 | Maintenance |
|
| React 18 | Stable |
|
| React 19 | Latest |
|
Comment auditer un site React en 7 étapes
Suivez ce guide étape par étape pour réaliser un audit RGAA complet de votre application React.
Configurer ESLint
Activez eslint-plugin-jsx-a11y en mode recommended ou strict. Bloquez les PR qui introduisent de nouvelles violations en CI.
Brancher axe-core en dev
Installez @axe-core/react. Les violations remontent dans la console pendant le développement local.
Lancer un scan RGAA Checker
L'audit sur les pages rendues identifie les erreurs détectables sur le DOM final, après hydratation et fetch (Puppeteer + axe-core).
Tester la navigation clavier
Sur chaque page critique, naviguez sans souris. Vérifiez le focus visible, l'ordre logique, le piégeage dans les modales.
Vérifier les annonces SPA
Sur chaque changement de route, vérifiez que le lecteur d'écran annonce la nouvelle page (titre, h1, ou live region). Next.js App Router le fait par défaut.
Tester avec un lecteur d'écran
NVDA + Firefox ou VoiceOver + Safari. Parcourez l'application sur trois scénarios utilisateur clés.
Documenter et publier la déclaration
Listez les non-conformités dans la grille RGAA. Publiez la déclaration d'accessibilité conformément au modèle DINUM.
Erreurs Fréquentes avec React
onClick sur des éléments non interactifs (RGAA 7.1)
Un <div> avec onClick n'est pas focalisable au clavier, n'a pas de rôle ARIA, n'est pas annoncé comme bouton. Erreur n°1 dans les audits React.
<div onClick={handleClick}>Envoyer</div><button type="button" onClick={handleClick}>Envoyer</button>outline: none sans alternative focus-visible
Le reset CSS supprime souvent l'outline globalement. Sans :focus-visible alternatif, plus aucun élément ne montre où est le focus (RGAA 10.7).
button { outline: none; }button:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }Modales sans piégeage du focus
Une modale ouverte doit piéger le focus à l'intérieur et le restaurer à l'élément déclencheur à la fermeture. Beaucoup d'implémentations « maison » oublient la restauration et renvoient au <body>.
Toasts dynamiques sans rôle ARIA
Un toast qui apparaît doit être annoncé. Sans role="status" (poli) ou role="alert" (assertif), le lecteur d'écran ne dit rien. Les bibliothèques react-hot-toast et sonner exposent les bons rôles.
Hiérarchie de titres figée dans les composants
Un composant Card qui force <h2> en interne casse la hiérarchie selon le contexte. Préférez un composant Heading qui accepte un niveau en prop, calculé depuis le contexte parent.
function Card({ title }) { return <h2>{title}</h2> }function Card({ title, level = 2 }) { const Tag = `h${level}` as const; return <Tag>{title}</Tag> }Routes SPA sans annonce
Le client-side routing ne déclenche pas de rechargement, donc le lecteur d'écran ne sait pas que la page a changé. Sans annonce explicite (focus sur h1, live region, document.title à jour), l'utilisateur reste perdu.
Packages à éviter
Ces packages sont connus pour causer des problèmes d'accessibilité. Évitez-les ou configurez-les correctement.
react-modal sans configuration
Sans setAppElement et configuration ARIA, ne gère pas le focus trap ni les annonces correctement.
Alternative : @base-ui-components/react Dialog, Radix Dialog ou React Aria Components
react-select v4 et antérieur
Accessibilité limitée, navigation clavier complexe, ARIA partiel.
Alternative : react-select v5+ ou @react-aria/components ComboBox
react-slick
Carrousel avec navigation clavier défaillante et pas de contrôle pause natif.
Alternative : Embla Carousel (a11y configurable) ou supprimer le carrousel
Reach UI
Bibliothèque historique en maintenance limitée, plutôt en fin de vie en 2026.
Alternative : React Aria Components, Base UI ou Radix Primitives
Bonnes Pratiques React
HTML sémantique d'abord
Utilisez les éléments natifs (button, input, nav, main, section) avant tout composant custom. Ils gèrent nativement le focus, le clavier et les rôles ARIA.
React Aria Components ou Base UI pour les composants composés
Pour combobox, listbox, tabs, treeview, menu : ne codez pas vous-même. React Aria Components (Adobe) couvre WAI-ARIA. Base UI 1.0 (MUI, février 2026, équipe Radix + Floating UI) propose 35+ composants headless accessibles.
useId pour les associations ARIA
React 18+ expose useId() qui génère des IDs uniques stables entre serveur et client. Parfait pour aria-labelledby, aria-describedby, label htmlFor.
Annonces de route en SPA
Trois méthodes : déplacer le focus sur le <h1> au montage, injecter le titre dans une live region aria-live="polite", ou utiliser Next.js App Router qui annonce automatiquement.
Tests automatisés axe + jest/vitest
Intégrez vitest-axe ou jest-axe sur chaque composant : expect(await axe(container)).toHaveNoViolations(). Storybook + addon-a11y pour la bibliothèque de composants.
Sélecteurs accessibles dans les tests
Utilisez getByRole, getByLabelText plutôt que getByTestId. Si vos tests dépendent de data-testid, c'est probablement parce que le composant n'expose pas le bon rôle accessible.
Lighthouse CI en complément
Lighthouse CI sur les pages critiques détecte les régressions. Pas un remplacement d'audit manuel, mais un canari utile en pipeline.
Critères RGAA clés pour React
Ces critères du référentiel RGAA sont particulièrement importants pour les sites React.
Compatibilité technologies d'assistance
Composants React doivent exposer des rôles ARIA corrects ou utiliser des éléments natifs (button, a, input).
Composants interactifs au clavier
Tous les composants custom doivent être utilisables au clavier (Tab, Entrée, Échap, flèches).
Landmarks ARIA
Layouts React (App Router ou React Router) doivent exposer main, nav, aside correctement, un seul main par page.
Focus visible
Le focus doit être visible sur tous les composants, y compris CSS-in-JS et reset CSS.
Étiquettes de formulaire
React Hook Form, Zod, ou formulaires natifs : label htmlFor lié à id, jamais le placeholder seul.
Liens d'évitement
Skip link au début du layout, focus géré sur le main au déclenchement.
Changement de contexte
Annonces de route en SPA via focus, document.title et live region.
Checklist accessibilité React
Vérifiez ces points essentiels avant de mettre votre site React en production.
- Tous les onClick sont sur des éléments focusables (button, a, input)
- eslint-plugin-jsx-a11y configuré en CI, sans nouvelle violation tolérée
- @axe-core/react actif en développement
- Modales avec piégeage du focus et restauration à la fermeture
- document.title à jour à chaque changement de route
- Focus déplacé sur <h1> ou main au montage de chaque route
- Toasts avec role="status" ou role="alert" selon urgence
- Composant Heading dynamique selon le contexte parent (pas de h2 figé)
- Tests vitest-axe / jest-axe sur composants critiques
- getByRole / getByLabelText utilisés à la place de getByTestId
- Composants composés (combobox, listbox, menu) issus de React Aria, Base UI ou Radix
- Lighthouse CI sur les pages publiques en pipeline
Questions Fréquentes sur React et l'accessibilité
React est-il accessible par défaut ?
Non. React est une bibliothèque UI agnostique. L'accessibilité dépend du HTML que vos composants produisent. JSX ne fait que générer du DOM, donc les règles HTML/ARIA restent les mêmes que partout ailleurs.
Faut-il préférer React Aria, Base UI ou Radix ?
Pour un nouveau projet en 2026, React Aria Components reste le choix le plus complet sur la couverture WAI-ARIA. Base UI 1.0 (sortie février 2026) est une alternative très sérieuse maintenue par MUI avec l'équipe Radix et Floating UI. Radix Primitives reste solide si vous l'utilisez déjà.
Comment annoncer un changement de route en SPA ?
Trois méthodes. La plus simple : déplacer le focus sur le <h1> au montage de la nouvelle page. La plus robuste : injecter le titre dans une live region aria-live="polite". Next.js App Router le fait automatiquement.
eslint-plugin-jsx-a11y suffit-il ?
Non. Il détecte les erreurs statiques (alt manquant, rôle invalide). Il ne voit pas les problèmes dynamiques (focus, ARIA dynamique, contraste calculé). Combinez-le avec axe-core en runtime et tests manuels au lecteur d'écran.
axe-core couvre-t-il le RGAA 4.1.2 ?
axe-core couvre une grande partie des critères WCAG 2.1, donc indirectement environ 30 à 40% des critères RGAA 4.1.2 qui en dérivent. Le reste demande une évaluation humaine.
Comment gérer une modale accessible en React ?
Utilisez la modale de React Aria, Base UI ou Radix plutôt que de coder la votre. Vous gagnez piégeage du focus, restauration, gestion ESC, ARIA dialog correct, scroll-lock. Si vous tenez à coder, ajoutez focus-trap-react.
React Native suit-il les mêmes règles ?
Partiellement. React Native a son propre système (accessibilityLabel, accessibilityRole). Les principes (clavier, contraste, annonces) sont les mêmes mais les API diffèrent. Le RGAA s'applique aussi aux applications mobiles.
Outils Recommandés pour React
eslint-plugin-jsx-a11y
Linter statique de référence pour JSX. Détecte alt manquant, rôle ARIA invalide, button sans label accessible. Configurable en mode recommended ou strict.
@axe-core/react
Plugin React qui injecte axe-core en développement et logue les violations dans la console. Pour les tests CI, utilisez @axe-core/playwright.
React Aria Components (Adobe)
Couche composants prête à l'emploi sur React Aria Hooks. Couvre WAI-ARIA Authoring Practices intégralement. Recommandé pour les nouveaux projets.
Base UI 1.0 (MUI)
Composants headless accessibles. Sortie 1.0 en février 2026 par l'équipe MUI avec contributeurs Radix et Floating UI. 35+ composants, focus performance et a11y.
Radix Primitives
Primitives headless très utilisées. Toujours maintenu, alternative solide à Base UI selon les préférences API.
vitest-axe / jest-axe
Matchers Vitest/Jest pour tester l'accessibilité avec axe-core dans les tests unitaires.
axe DevTools (Deque)
Extension navigateur Chrome/Firefox pour audit manuel d'une page rendue. Complète les tests automatisés.
Auditez votre site React gratuitement
Vérifiez si votre application respecte les 106 critères RGAA en moins de 30 secondes.
Lancer un audit RGAA gratuit