Aller au contenu principal

Accessibilite React : guide RGAA complet

Guide complet pour rendre vos applications React accessibles selon le RGAA : semantique HTML, focus, formulaires, aria-live et checklist.

20 min de lectureDebutant a avance

1. Pourquoi l'accessibilité est cruciale en React

React a révolutionné le développement front-end en introduisant un modèle déclaratif basé sur des composants réutilisables et un Virtual DOM. Cette abstraction offre des gains énormes en productivité et en maintenabilité, mais elle crée aussi une distance entre le développeur et le HTML réel généré dans le navigateur. Or, l'accessibilité repose fondamentalement sur la qualité du HTML : structure sémantique, attributs ARIA, ordre logique du DOM, gestion du focus.

En France, le RGAA 4.1.2 impose des critères stricts d'accessibilité qui s'appliquent à toute application web, quelle que soit la technologie utilisée. Une application React qui ne respecte pas ces critères expose son organisation à dessanctions pouvant atteindre 50 000 euros par siteavec l'European Accessibility Act.

Au-delà de l'aspect légal, l'accessibilité concerne 15% de la population mondiale en situation de handicap. Les déficiences visuelles, motrices, auditives et cognitives impactent la façon dont les utilisateurs interagissent avec vos interfaces. Un composant React peut paraître parfait visuellement mais être totalement inutilisable avec un lecteur d'écran ou un clavier.

Ce guide couvre les spécificités de l'accessibilité dans le contexte React : les pièges à éviter, les patterns à adopter, les critères RGAA les plus concernés et les outils pour automatiser une partie de la vérification. L'objectif est de vous donner les connaissances nécessaires pour intégrer l'accessibilité dans votre workflow de développement React au quotidien.

2. Erreurs d'accessibilité courantes en React

Voici les erreurs les plus fréquemment rencontrées dans les applications React, et pourquoi elles posent problème :

Images sans alternative textuelle

En React, il est facile d'oublier l'attributaltsur les balises<img>ou sur le composantnext/image. Sans alternative textuelle, les lecteurs d'écran annoncent le chemin du fichier ou rien du tout. Pour les images décoratives, utilisezalt=""explicitement plutôt que d'omettre l'attribut, afin que le lecteur d'écran ignore l'image.

Utilisation de div et span comme éléments interactifs

L'une des erreurs les plus répandues est d'attacher unonClicksur un<div>ou un<span>. Ces éléments ne sont pas focusables par défaut, ne déclenchent pas d'action au clavier (Entrée ou Espace) et ne sont pas annoncés comme interactifs par les lecteurs d'écran. Il faudrait alors ajouterrole="button",tabIndex={0}et un gestionnaireonKeyDown. Mais la solution la plus simple et la plus robuste est d'utiliser un<button>natif.

Absence de gestion du focus après navigation SPA

Dans une Single Page Application, le changement de route ne déclenche pas de rechargement de page. Les lecteurs d'écran ne sont donc pas automatiquement informés que le contenu a changé. Le focus reste sur l'élément qui a déclenché la navigation (un lien, par exemple), et l'utilisateur ne sait pas que du nouveau contenu est apparu. C'est une violation du critère RGAA 12.1 sur la navigation.

Mauvaise utilisation des attributs ARIA en JSX

React utilise le camelCase pour la plupart des attributs HTML, mais les attributsaria-*etdata-*conservent leur syntaxe avec des tirets. Cela peut créer de la confusion. De plus, certains développeurs ajoutent des attributs ARIA de façon excessive ou incorrecte, ce qui peut dégrader l'expérience plutôt que l'améliorer. La règle d'or : pas d'ARIA est mieux que du mauvais ARIA.

Contenu dynamique non annoncé

React excelle dans les mises à jour dynamiques de l'interface : notifications, messages de validation, chargement de données. Mais sans regionsaria-live, ces changements sont invisibles pour les utilisateurs de lecteurs d'écran. Le contenu apparaît à l'écran mais n'est jamais annoncé, rendant l'application inutilisable pour les personnes malvoyantes.

3. Bonnes pratiques avec exemples de code

Privilégier le HTML sémantique

Le HTML sémantique est la fondation de l'accessibilité. Utilisez<button>,<nav>,<main>,<header>,<section>plutôt que des<div>partout. Les éléments natifs embarquent des comportements d'accessibilité gratuits : focus, rôles ARIA implicites, interactions clavier.

Gestion du focus avec useRef et useEffect

Après une navigation SPA ou l'ouverture d'une modale, il est essentiel de déplacer le focus au bon endroit. React fournituseRefetuseEffectpour gérer cela de manière déclarative.

L'attributtabIndex={-1}rend l'élément focusable par JavaScript sans l'ajouter à l'ordre de tabulation naturel. C'est le pattern recommandé pour les titres qui doivent recevoir le focus programmatiquement.

Régions aria-live pour le contenu dynamique

Utilisezaria-livepour informer les lecteurs d'écran des changements de contenu.politeattend que le lecteur termine sa phrase actuelle,assertiveinterrompt immédiatement (à utiliser avec parcimonie).

Formulaires accessibles

Les formulaires sont une source majeure de problèmes d'accessibilité. Chaque champ doit avoir un label explicite, les erreurs doivent être associées aux champs viaaria-describedby, et les champs obligatoires doivent utiliseraria-requiredou l'attribut natifrequired.

Points importants : l'attributhtmlFor(équivalent deforen HTML) associe le label au champ. L'étoile décorative est masquée avecaria-hidden="true"pour éviter que les lecteurs d'écran annoncent "étoile". Le vrai signal d'obligation est porté pararia-required.

Navigation clavier avec onKeyDown

Quand vous créez des composants interactifs personnalisés (onglets, menus, sliders), vous devez implémenter la navigation clavier. Suivez les patterns du WAI-ARIA Authoring Practices pour chaque type de composant.

Ce pattern utilise le roving tabindex : seul l'onglet actif atabIndex={0}, les autres onttabIndex={-1}. L'utilisateur navigue entre les onglets avec les flèches et entre/sort du groupe avec Tab.

React.Fragment pour éviter les noeuds DOM superflus

Les<div>d'encapsulation inutiles polluent l'arbre DOM et peuvent perturber les structures sémantiques (par exemple, insérer un<div>entre un<ul>et ses<li>). UtilisezReact.Fragmentou la syntaxe courte<>...</>pour grouper des éléments sans ajouter de noeud DOM.

4. Critères RGAA essentiels pour React

Parmi les 106 critères du RGAA, certains sont particulièrement impactés par l'utilisation de React. Voici les quatre critères les plus critiques et leurs implications pour les développeurs React :

Critère 1.1 — Images : alternative textuelle

Chaque image porteuse d'information doit posséder une alternative textuelle pertinente. En React, cela concerne les balises<img>, le composantnext/image, les SVG inlines et les icônes. Les images décoratives doivent avoiralt=""ouaria-hidden="true".

Critère 7.1 — Scripts : compatibilité avec les technologies d'assistance

Ce critère est central pour React puisque toute l'application est générée par JavaScript. Chaque composant interactif doit être utilisable au clavier, avoir un nom accessible, un rôle et un état ARIA corrects. Les changements de contenu dynamiques doivent être restitués par les technologies d'assistance.

Concrètement, chaque bouton, lien, menu déroulant, onglet, accordéon ou modale doit fonctionner intégralement au clavier. Testez avec Tab, Shift+Tab, Entrée, Espace, Échap et les flèches directionnelles. Si un composant ne fonctionne pas sans souris, il viole ce critère.

Critère 11.1 — Formulaires : présence d'étiquettes

Chaque champ de formulaire doit posséder une étiquette (label). En React, utilisezhtmlForsur le<label>associé à l'iddu champ. Ne remplacez jamais un label par un simple placeholder : les placeholders disparaissent à la saisie et n'ont pas de rôle sémantique de label.

Critère 12.1 — Navigation : présence d'un système de navigation

Chaque ensemble de pages doit proposer au moins deux systèmes de navigation parmi : menu, plan du site, moteur de recherche. En React SPA, le routeur côté client ne déclenche pas de rechargement de page. Vous devez donc gérer manuellement l'annonce des changements de page, la mise à jour du titre et le déplacement du focus. Les liens d'évitement ("Aller au contenu principal") doivent être fonctionnels et visibles au focus. Vérifiez que votre barre de navigation utilise une balise<nav>avec unaria-labeldistinct pour chaque zone de navigation.

5. Outils et packages recommandés

L'écosystème React dispose d'outils puissants pour intégrer l'accessibilité à chaque étape du développement. Voici les packages incontournables :

1

eslint-plugin-jsx-a11y

Plugin ESLint qui détecte les erreurs d'accessibilité directement dans votre éditeur de code. Il vérifie la présence des attributs alt, les rôles ARIA valides, les éléments interactifs sans gestionnaire clavier, et bien d'autres règles. À intégrer dans votre CI/CD pour bloquer les régressions.

2

@testing-library/react

Librairie de test qui encourage les bonnes pratiques en utilisant les requêtes basées sur les rôles ARIA et les labels accessibles plutôt que sur les sélecteurs CSS ou les test-ids. Si votre composant n'est pas trouvable pargetByRoleougetByLabelText, c'est probablement un signe de problème d'accessibilité.

3

@axe-core/react

Intègre le moteur d'audit axe-core directement dans votre application React en mode développement. À chaque rendu, il analyse le DOM et affiche les violations d'accessibilité dans la console du navigateur. Idéal pour détecter les problèmes au fil du développement sans ouvrir un outil externe.

4

React Aria (Adobe)

Collection de hooks React qui implémentent les patterns ARIA de manière accessible. Plutôt que de construire vos propres composants avec des roles et des interactions clavier complexes, React Aria fournit des hooks commeuseButton,useDialog,useComboBox,useMenuqui gèrent le focus, le clavier et les attributs ARIA automatiquement. C'est la référence en matière de composants accessibles sans style imposé.

6. Checklist accessibilité React

Utilisez cette checklist comme référence lors du développement et de la revue de code de vos composants React :

Structure et sémantique

  • Utilisation de balises HTML sémantiques (button,nav,main,header,footer) au lieu dedivpour les éléments interactifs et les landmarks
  • Hiérarchie de titres logique (h1 à h6) sans saut de niveaux
  • Utilisation de Fragment au lieu de div d'encapsulation quand le noeud DOM n'est pas nécessaire
  • Lien d'evitement "Aller au contenu principal" present et fonctionnel

Images et médias

  • Toutes les images informatives ont un attributaltdescriptif
  • Les images décoratives ontalt=""ouaria-hidden="true"
  • Les SVG interactifs ou informatifs ontrole="img"et unaria-labelou un<title>
  • Les icônes dans les boutons avec texte ontaria-hidden="true"etfocusable="false"

Formulaires

  • Chaque champ a un<label>explicitement associé viahtmlFor
  • Les erreurs de validation sont associées aux champs viaaria-describedby
  • Les champs invalides utilisentaria-invalid="true"
  • Les champs obligatoires utilisentrequiredouaria-required="true"
  • Les groupes de champs radio/checkbox sont dans un<fieldset>avec<legend>

Interactions et navigation

  • Tous les éléments interactifs sont accessibles au clavier (Tab, Entrée, Espace, Échap)
  • Le focus est visible sur tous les éléments interactifs (outline visible)
  • Le focus est géré après chaque changement de route SPA
  • Les modales implémentent un focus trap et restaurent le focus a la fermeture
  • L'ordre de tabulation suit l'ordre visuel logique

Contenu dynamique et ARIA

  • Les mises à jour dynamiques utilisentaria-livepour être annoncées
  • Les états de chargement sont communiqués (aria-busy, texte de chargement accessible)
  • Les rôles ARIA ne sont utilisés que quand le HTML sémantique ne suffit pas
  • Le titre de la page (document.title) est mis à jour à chaque changement de route

Tests et outillage

  • eslint-plugin-jsx-a11y activé dans la CI/CD
  • Tests unitaires utilisantgetByRoleetgetByLabelTextplutôt quegetByTestId
  • Test manuel au clavier effectué sur chaque composant interactif
  • Test avec au moins un lecteur d'écran (NVDA, VoiceOver ou JAWS)

Questions fréquentes

React est-il accessible par defaut ?

Non. React fournit les outils necessaires, mais ne force aucune bonne pratique d'accessibilite.

Comment tester l'accessibilite d'une application React ?

Combinez eslint-plugin-jsx-a11y, axe, testing-library et des tests manuels avec lecteur d'ecran et navigation clavier.

Quelle est la difference entre aria-label et aria-labelledby en React ?

aria-label fournit un libelle direct. aria-labelledby reference un texte visible existant et doit etre privilegie quand il est disponible.

Comment gerer le focus apres une navigation dans une SPA React ?

Deplacez le focus vers le contenu principal ou le h1 apres chaque changement de route et annoncez la navigation via une region aria-live si necessaire.

Faut-il utiliser des librairies de composants accessibles ou tout coder soi-meme ?

Utiliser React Aria, Radix UI ou Headless UI est fortement recommande pour les patterns ARIA complexes.

Les portals React posent-ils des problemes d'accessibilite ?

Oui, notamment pour les modales si le focus n'est pas piege et restaure correctement a la fermeture.

Comment rendre les animations React accessibles ?

Respectez prefers-reduced-motion et annoncez correctement les changements dynamiques quand le contenu evolue.

Le Server-Side Rendering ameliore-t-il l'accessibilite de React ?

Le SSR aide en livrant du HTML complet plus tot, mais il ne corrige pas les erreurs de semantique, de focus ou d'ARIA.

Verifiez l'accessibilite de votre application React

RGAA Scanner analyse automatiquement votre site React et detecte les non-conformites RGAA avec des recommandations de correction.

Testez votre site gratuitement