Chaque script est-il, si nécessaire, compatible avec les technologies d’assistance ?
Un utilisateur aveugle navigue dans un accordéon JavaScript. Les sections s’ouvrent et se ferment visuellement, mais son lecteur d’écran annonce juste « section à déplier », sans rôle, sans état, sans indication qu’il se passe quoi que ce soit. Pour lui, le composant n’existe pas fonctionnellement.
Ce critère s’applique à tous les composants d’interface créés ou pilotés par JavaScript : accordéons, modales, onglets, menus déroulants, carrousels, sliders. Chacun doit remplir trois conditions simultanément : avoir un rôle cohérent avec son usage (role="button", role="tab", role="dialog"), porter un nom explicite, et — si le composant gère un état — refléter cet état via des attributs ARIA (aria-expanded, aria-selected, aria-checked).
La règle de l’alternative existe, mais c’est la solution de dernier recours. Si un composant inaccessible est accompagné d’un équivalent natif ou d’un lien donnant accès aux mêmes fonctionnalités, le critère est satisfait. Dans la pratique, mieux vaut rendre le composant lui-même accessible dès le départ.
L’erreur la plus fréquente en audit : les composants sont opérables au clavier, mais muets pour les lecteurs d’écran. Opérable n’est pas accessible.
3 tests pour s'assurer que les scripts restent compatibles avec les technologies d'assistance
Rôle, nom et état des composants JavaScript
- Identifiez tous les composants d’interface créés ou pilotés par JavaScript : accordéons, modales, onglets, carrousels, menus, sliders, etc.
- Pour chaque composant, vérifiez les trois points suivants :
- Il possède un rôle cohérent avec sa fonction (
role="button"pour un déclencheur,role="tab"pour un onglet,role="dialog"pour une modale) - Il possède un nom explicite (texte visible,
aria-labelouaria-labelledby) - Si le composant contrôle un état (affichage/masquage, sélection, activation), son nom ou ses attributs ARIA reflètent cet état (
aria-expanded,aria-selected,aria-checked)
- Il possède un rôle cohérent avec sa fonction (
- Si ces trois conditions ne sont pas remplies, vérifiez la présence d’un composant natif accessible permettant les mêmes fonctionnalités.
- À défaut, vérifiez la présence d’une alternative accessible (lien, texte, autre mécanisme) donnant accès aux mêmes fonctionnalités.
- Si l’une des conditions des étapes 2, 3 ou 4 est satisfaite, le test est validé.
Restitution des composants JavaScript par lecteur d'écran
- Pour chaque composant ayant passé le test 7.1.1, testez-le avec au moins une combinaison de référence lecteur d’écran/navigateur (NVDA + Firefox, VoiceOver + Safari).
- Vérifiez que le lecteur d’écran annonce correctement le rôle, le nom et l’état du composant, et que les changements d’état sont vocalisés lors de l’interaction.
- Si la restitution est incorrecte ou incomplète, vérifiez qu’une alternative accessible permet d’accéder aux mêmes fonctionnalités.
- Si c’est le cas, le test est validé.
Pertinence du nom et du rôle des composants JavaScript
- Pour chaque composant ayant passé le test 7.1.1, vérifiez :
- Son intitulé visible est pertinent (il décrit clairement la fonctionnalité)
- Son rôle est pertinent pour l’usage réel du composant
- Si le composant dispose d’un nom accessible (
aria-labelouaria-labelledby), vérifiez que ce nom :- Est pertinent
- Contient au moins le texte de l’intitulé visible (exigence WCAG 2.5.3)
- Si ces conditions sont remplies, le test est validé.
Exemples
❌ Non conforme : Accordéon sans rôle ni état ARIA
<div class="accordion-header" onclick="toggleSection(this)" tabindex="0">
Politique de retour
</div>
<div class="accordion-panel" style="display:none">
<p>Vous disposez de 30 jours pour retourner votre commande.</p>
</div>Le <div> est atteignable au clavier via tabindex, mais un lecteur d’écran annonce uniquement « Politique de retour », sans indiquer qu’il s’agit d’un élément interactif. Aucun état n’est communiqué : l’utilisateur ne sait pas si la section est ouverte ou fermée, ni même qu’il peut interagir avec cet élément.
✅ Conforme : Accordéon avec rôle, nom et état ARIA corrects
<button type="button" aria-expanded="false" aria-controls="section-retour">
Politique de retour
</button>
<div id="section-retour" hidden>
<p>Vous disposez de 30 jours pour retourner votre commande.</p>
</div>
<script>
document.querySelector('[aria-controls="section-retour"]')
.addEventListener('click', function () {
const expanded = this.getAttribute('aria-expanded') === 'true';
this.setAttribute('aria-expanded', String(!expanded));
document.getElementById('section-retour').hidden = expanded;
});
</script>Le <button> natif porte son rôle implicitement. aria-expanded="false" annonce l’état fermé ; au clic, la valeur passe à "true" et le lecteur d’écran vocalise immédiatement le changement. L’utilisateur sait ce qu’il déclenche et ce qui s’est passé.
❌ Non conforme : Nom accessible ne contenant pas l’intitulé visible
<button type="button" aria-label="Supprimer l’article">
<svg aria-hidden="true" focusable="false" width="16" height="16">
<use href="#icon-trash"></use>
</svg>
Retirer
</button>L’intitulé visible est « Retirer », mais le nom accessible est « Supprimer l’article ». Ce nom ne contient pas le texte visible, ce qui viole WCAG 2.5.3. Un utilisateur de commande vocale qui dit « cliquer Retirer » ne trouvera pas le bon bouton car les logiciels de reconnaissance s’appuient sur le nom accessible.
✅ Conforme : Nom accessible enrichissant l’intitulé visible
<button type="button" aria-label="Retirer l’article Chemise bleue du panier">
<svg aria-hidden="true" focusable="false" width="16" height="16">
<use href="#icon-trash"></use>
</svg>
Retirer
</button>Le nom accessible commence par le texte visible « Retirer » et y ajoute un contexte utile. La commande vocale fonctionne, et les lecteurs d’écran obtiennent plus d’informations que le seul intitulé visible. Test 7.1.3 et WCAG 2.5.3 sont satisfaits.
Astuces et pièges
⚠️ Focusable ne veut pas dire accessible
Un <div tabindex="0" onclick="..."> est atteignable au clavier, mais un lecteur d’écran l’annonce comme du texte brut, sans rôle interactif. Les deux propriétés sont indépendantes. C’est la confusion la plus fréquente en audit sur ce critère.
⚠️ aria-expanded déclaré mais jamais mis à jour
Un accordéon avec aria-expanded="false" statique en HTML qui ne change jamais est pire qu’un accordéon sans attribut : il annonce constamment « fermé » même quand il est ouvert. L’attribut doit être mis à jour dynamiquement par JavaScript à chaque interaction, pas seulement présent au chargement de la page.
💡 Préférer les éléments HTML natifs
Un <button> embarque rôle, focusabilité, activation clavier (Entrée et Espace) et annonce lecteur d’écran sans une ligne d’ARIA. Un <div role="button"> demande de tout recoder manuellement. La règle : utiliser ARIA uniquement quand aucun élément HTML natif ne correspond à l’usage.
⚠️ L’alternative accessible doit couvrir les mêmes fonctionnalités
Si un composant JavaScript complexe (slider de plage de prix, carte interactive) n’est pas accessible, l’alternative doit donner accès aux mêmes fonctionnalités, pas à une version appauvrie. Un lien « Voir la liste des prix » est valable si le slider ne sert qu’à filtrer une liste accessible par ailleurs. Une mention « fonctionnalité non disponible sur mobile » ne constitue pas une alternative.
⚠️ Test 7.1.3 : le nom accessible doit contenir l’intitulé visible
Un aria-label qui reformule l’intitulé visible échoue au test 7.1.3 et viole WCAG 2.5.3. Le nom accessible peut enrichir le texte visible, mais doit le contenir. aria-label="Ajouter au panier — Chemise bleue taille L" pour un bouton « Ajouter au panier » : correct. aria-label="Commander" pour le même bouton : non conforme.
⚠️ Composant inaccessible avec alternative valide : le critère passe
Un lecteur média JavaScript non accessible ne fait pas échouer le critère si un lien de téléchargement permet d’accéder au même fichier audio ou vidéo. L’alternative doit être visible, fonctionnelle et mentionner explicitement son rôle de substitution.
Questions fréquentes
Quelle est la différence entre le test 7.1.1 et le test 7.1.3 en RGAA ?
Le test 7.1.1 vérifie l’existence et la cohérence : le composant a-t-il un rôle et un nom logiques ? Le test 7.1.3 vérifie la qualité et la correspondance : le nom accessible est-il pertinent et contient-il au moins le texte visible ? Un composant peut valider 7.1.1 (il a un rôle et un nom) et échouer 7.1.3 si son aria-label ne reprend pas l’intitulé visible. Les deux tests sont complémentaires.
Pourquoi tester la compatibilité RGAA avec un lecteur d'écran réel plutôt qu'un outil automatique ?
Le test 7.1.2 exige une vérification de la restitution réelle. Les outils automatiques détectent les absences d’attributs ARIA, mais ne peuvent pas vérifier que NVDA annonce correctement un état dynamique après interaction. Testez avec au moins une combinaison de référence RGAA : NVDA et Firefox, ou VoiceOver et Safari.
Comment une alternative accessible valide-t-elle le critère RGAA 7.1 malgré un composant inaccessible ?
Oui, à condition que l’alternative soit réellement équivalente et que l’utilisateur soit informé de son existence. Elle doit donner accès aux mêmes fonctionnalités, sans perte d’information ni étape discriminatoire. Un lien « Version accessible » vers une page dégradée qui supprime des fonctions ne constitue pas une alternative valide.
Pourquoi un <div role="button"> sans tabindex est-il non conforme au critère RGAA 7.1 ?
Oui. Sans tabindex="0", l’élément n’est pas atteignable au clavier, donc inutilisable par les lecteurs d’écran qui naviguent à la touche Tab. Le composant échoue aussi au critère 7.3 qui exige la gestion clavier des scripts. L’élément <button> natif évite ces deux problèmes d’emblée.
Comment vérifier qu'un nom accessible contient bien l'intitulé visible selon le test 7.1.3 ?
Ouvrez l’inspecteur d’accessibilité du navigateur (onglet « Accessibilité » dans les DevTools Chrome ou Firefox) et relevez le nom accessible calculé. Comparez-le avec le texte visible dans l’interface. Le nom accessible doit contenir ce texte visible, hors ponctuation et différences de casse. Si un aria-label ou aria-labelledby est présent, c’est lui qui prime sur le contenu textuel de l’élément.