Des scripts accessibles avec le RGAA
Les critères du référentiel général d'amélioration de l'accessibilité
L’accessibilité des scripts est certainement la thématique la plus difficile du référentiel RGAA. Ces éléments sont en effet parmi les plus complexes à rendre utilisables à la navigation ou pour les technologies d’assistance. Je vous partage mes conseils et mon expérience pour vous aider à améliorer la compatibilité de vos scripts avec le RGAA.
Introduction : la notion de script
Un script est un ensemble d’instructions informatiques exécutées dynamiquement afin d’enrichir l’interactivité et les fonctionnalités d’une page web ou d’une application. Contrairement au contenu HTML statique, le script permet de modifier le comportement de la page en temps réel sans nécessiter un rechargement complet.
Le script est toujours introduit par une balise <script>. Il peut être directement écrit dans le code source de la page, ou placé dans une ressource externe qui est appelée depuis la page web. Le JavaScript est le langage de script par excellence, et c’est d’ailleurs celui qui est cité en exemple dans le RGAA.
Le référentiel général d’amélioration de l’accessibilité s’intéresse uniquement aux scripts exécutés côté client, c’est-à-dire par le navigateur de l’internaute.
Le JavaScript est un langage de programmation principalement utilisé pour apporter de l’interactivité aux sites internet. Alors que le HTML définit le contenu (texte, images) et le CSS l’apparence (couleurs, polices), le JavaScript permet d’ajouter des comportements dynamiques. Il s’exécute directement dans le navigateur de l’utilisateur, ce qui lui permet de modifier ce qui s’affiche à l’écran sans avoir besoin de charger une nouvelle page.
Concrètement, c’est grâce au JavaScript qu’un menu se déroule quand on clique dessus, qu’une carte géographique devient zoomable, ou qu’un message d’erreur apparaît instantanément si vous oubliez de remplir une case dans un formulaire.
Les principaux atouts du JavaScript sont :
- L’interactivité, avec une réaction immédiate aux actions de l’utilisateur (clics, survol de la souris, frappe au clavier).
- La mise à jour en temps réel, pour modifier le texte ou les images d’une page ou d’un formulaire instantanément.
- L’exécution locale, avec un code lu et traité par votre propre ordinateur grâce à votre navigateur web.
L’exécution d’un script peut être le seul moyen d’accéder à un contenu ou une fonctionnalité. Or, le principe d’équivalence est au coeur de la vocation du RGAA : une personne en situation de handicap doit bénéficier de la même information et des mêmes services qu’un internaute valide.
Il est donc normal que tous les scripts présents dans la page soient rendus accessibles, ou des alternatives conformes au RGAA soient proposées.
L’option CTRL+U :
L’analyse du code source statique, accessible via le raccourci CTRL+U (ou Cmd+U sur Mac), permet d’identifier les balises <script> avant leur exécution. Ce code source “brut” est celui envoyé par le serveur, avant toute modification par JavaScript. Certains scripts peuvent modifier le DOM après chargement, donc ce qu’on voit dans “Inspecter” peut différer du code source brut. Recherchez les attributs d’événements tels que onclick, onfocus, onkeypress, onmouseover, onload… : ce sont des attributs HTML qui lient directement une instruction JavaScript à un élément de la page. Ils peuvent réagir à une action de l’utilisateur ou s’exécuter automatiquement.
Les outils de développement :
Les outils de développement présents dans le navigateur, disponibles par un clic droit et “Inspecter” ou la touche F12, sont également utiles. Vous pouvez passer par l’onglet Réseau (ou Network), recharger la page (F5), puis filtrer par “JS”, mais vous aurez parfois des listes interminables de fichiers. Je vous conseille plutôt d’utiliser un script dédié que vous exécutez dans la console, car vous risquez bien, sinon, d’être noyé par les scripts. Le script filtrera automatiquement les éléments pertinents pour l’audit RGAA.
La désactivation du JavaScript :
Autre méthode : désactivez le JavaScript et identifiez les fonctionnalités manquantes. Cette approche n’est pas toujours optimale, car certains sites accessibles deviennent quasiment inutilisables une fois le JavaScript désactivé, alors qu’ils sont en réalité conformes au RGAA.
1. Vérifier la compatibilité des scripts avec les technologies d'assistance
Vous devez identifier tous les scripts qui génèrent ou qui contrôlent un composant d’interface présents dans une page, et vous assurer qu’ils sont compatibles avec les technologies d’assistance.
Un script est considéré comme conforme au RGAA lorsque le nom, le rôle, la valeur, le paramétrage et les changements d’états sont accessibles aux technologies d’assistance :
- Le nom permet d’identifier le composant. Il peut par exemple s’agir de l’intitulé d’un bouton.
- Le rôle détermine le type d’élément (bouton, liste à cocher, slider, etc.).
- La valeur représente l’état actuel des données, et elle change au cours de l’utilisation.
- Le changement d’état est une information binaire sur le composant (par exemple, ouvert ou fermé, coché ou non coché, etc.).
- Le paramétrage détermine l’interaction de l’élément avec le reste de la page.
Vous pouvez également contourner le problème en proposant un autre composant d’interface ou une alternative qui offre les mêmes fonctionnalités.
Tout composant interactif doit posséder un nom accessible. Les noms accessibles les plus courants sont, par ordre de priorité :
- Un
aria-labelledby; - Un
aria-label; - Le contenu de la balise ou l’attribut
Altpour un composant d’interface de type image ; - L’attribut
title.
Ce nom doit être pertinent, en permettant à l’utilisateur de comprendre l’objectif du composant.
Par exemple, <button>X</button> pour ferme une fenêtre modale n’est pas pertinent, car une technologie d’assistance vocaliserait la lettre X. Entre autres options, une modification de l’intitulé ou l’ajout d’un aria-label permet de retrouver une conformité:
<button>Fermer</button><button aria-label="Fermer la fenêtre : X">X</button>
Note : le nom accessible doit toujours reprendre l’intitulé, pour faciliter l’utilisation avec des commandes vocales.
La pertinence du rôle dépend de l’action réelle du script (déplier un menu, ouvrir une modale, etc.).
Le rôle est inapproprié si le déclencheur ne correspond pas à l’objectif fonctionnel : par exemple, un bouton déclenchant l’ouverture d’une fenêtre modale ne peut pas être un simple lien, mais nécessite une balise <button> ou un role="button".
Le changement d’état apporte parfois une information clé dans l’utilisation d’un composant d’interface, et doit donc être accessible aux technologies d’assistance.
Imaginez par exemple un bouton permettant d’ajouter un article à une liste de favoris. Il est important de préciser aux technologies d’assistance si l’article est déjà sélectionné ou non. Vous pouvez rendre l’état accessible en utilisant l’attributaria-pressed :
- Non sélectionné :
<button aria-pressed="false">Ajouter aux favoris</button>; - Sélectionné :
<button aria-pressed="true">Ajouter aux favoris</button>.
Vous pouvez aussi changer l’intitulé du bouton : <button>Ajouter aux favoris</button> devient <button>Retirer des favoris</button>
Astuces et tutoriels sur l'accessibilité Web
2. Les alternatives aux scripts sont-elles pertinentes
Exemples d’alternatives aux scripts
Vous affichez un calendrier non accessible pour sélectionner la date d’un séjour ou d’un trajet en train. Une alternative au calendrier est un champ de saisie de la date avec une indication et un exemple de format visibles : Format attendu JJ/MM/YYYY, par exemple 28/05/2026. Si ce composant d’interface est un champ de saisie accessible qui offre les mêmes fonctionnalités, vous êtes conforme au RGAA.
Vous présentez vos points de vente avec une carte interactive non accessible. Vous pouvez simplement proposer une liste textuelle structurée qui reprend les mêmes informations.
Le critère 7.2.1du RGAA (version 4.1.2) intègre la phrase suivante : La page affichée, lorsque JavaScript est désactivé, permet d’accéder à des contenus et des fonctionnalités similaires.
.
Cette phrase doit être remise dans son contexte : ce n’est qu’une option de conformité parmi d’autres pour les scripts qui débutent par la balise <script>.
Le JavaScript est incontournable en 2025, et il est parfois indispensable pour faire fonctionner correctement votre site web. Gardez toujours à l’esprit que le référentiel général d’amélioration de l’accessibilité prône l’équivalence : si votre site web ne fonctionne pas correctement pour tous les utilisateurs sans JS, vous ne dégradez pas uniquement l’expérience des personnes en situation de handicap car tout le monde est logé à la même enseigne.
Vous pouvez donc avoir un site conforme au RGAA qui a obligatoirement besoin de JavaScript pour fonctionner (à condition de rendre accessibles tous les scripts concernés).
Il n’existe malheureusement pas d’outil automatisé qui permette de réaliser de façon totalement efficace ce travail de contrôle. Seul un examen minutieux de la page permet de vous assurer que tous les composants d’interface associés à un script possèdent le cas échéant une alternative accessible.
3. Une navigation et un contrôle des composants au clavier
Certains utilisateurs en situation de handicap ne peuvent pas utiliser de souris et naviguent avec leur clavier grâce à la touche Tabulation (Tab) ou avec un dispositif de pointage adapté à leur handicap.
Chaque composant d’interface doit être accessible et actionnable lors d’une navigation au clavier.
Par ailleurs, un script ne doit pas supprimer le focus d’un élément qui doit normalement le recevoir. Cela interromprait la navigation au clavier, ce qui n’est pas l’idéal pour un utilisateur.
Imaginez un bouton « Modifier la quantité » entouré d’un liseré de focus. Lorsque l’utilisateur l’active, un script remplace instantanément ce bouton par un champ de saisie, mais supprime l’élément original sans déplacer le focus sur le nouveau champ.
Le focus est alors perdu : le liseré disparaît et la navigation est interrompue. En réappuyant sur Tabulation, l’utilisateur repart du début de la page au lieu de continuer sa saisie, brisant la cohérence de la navigation.
Vous pouvez corriger cette suppression de focus en redirigeant le focus vers le nouveau champ grâce à la méthode .focus(): dès que le script génère le champ de saisie, il appelle cette fonction pour y placer immédiatement le liseré. L’utilisateur peut ainsi poursuivre sa saisie sans aucune rupture de navigation.
Il n’existe malheureusement pas d’outil automatisé qui permette de réaliser de façon totalement efficace ce travail de contrôle. Seul un examen minutieux de la page permet de vous assurer que tous les composants d’interface associés à un script possèdent le cas échéant une alternative accessible.
4. La gestion d'un changement de contexte
Certains scripts apportent un changement de contexte. Voici quelques exemples concrets de changements de contexte :
- La mise à jour dynamique des champs d’un formulaire : vous cliquez sur “J’ai des enfants” et des champs supplémentaires sur le nombre, l’âge ou le sexe des enfants apparaissent ;
- Le lancement automatique d’un média : vous sélectionnez une playlist et une vidéo, un podcast ou une chanson se lance automatiquement ;
- La mise à jour grâce à un procédé AJAX d’une partie essentielle de la page : vous précisez votre statut professionnel et un contenu personnalisé sur vos solutions de prévoyance s’affiche ;
- La manipulation du focus qui modifie la position de l’internaute dans la page : vous filtrez une liste de résultats par marque, et le focus est déplacé sur le premier produit de la liste filtrée.
L’internaute qui utilise une technologie d’assistance doit être informé de ce changement de contexte :
- En amont du déclenchement, par un composant d’interface ou un lien au nom accessible explicite ;
- Lors du déclenchement, par un message accessible qui précise les conséquences de l’action et la nature du changement de contexte.
En effet, l’expérience offerte à un internaute malvoyant utilisant un lecteur d’écran serait très fortement dégradée, car il ne pourrait pas prendre toute la mesure du changement de contexte. Il pourrait être amené à penser à un bug ou se retrouverait tout simplement bloqué.
Pour rendre un changement de contexte accessible sans déplacer le focus, on utilise l’attribut aria-live. Il permet aux technologies d’assistance d’annoncer vocalement les mises à jour dynamiques de la page (AJAX, messages d’erreur, notifications).
aria-live="polite": le lecteur d’écran attend que l’utilisateur ait fini sa lecture ou son action avant d’annoncer le changement. C’est la solution à privilégier dans l’immense majorité des casaria-live="assertive": l’annonce est immédiate et interrompt toute lecture en cours. À réserver aux alertes critiques ou urgentes.
5. La restitution des messages de statut
Un message de statut informe l’utilisateur d’un changement de contenu ou de la réussite d’une action sans interrompre son activité en cours. Le message de statut ne s’accompagne pas d’un changement de contexte.
Voici quelques exemples de messages de statut :
- L’ajout d’un article au panier s’accompagne d’un message “article ajouté au panier avec succès” ;
- L’information de l’avancée d’un téléchargement à des moments clés (25 %, 50 %, 75 %…) ;
- L’annonce d’une erreur, comme la présence de champs avec des données invalides ;
- Etc.
Plusieurs rôles et modèles de conception peuvent vous permettre d’intégrer des messages de statut accessibles :
role="alert";role="status";role="log";role="progressbar".
Le role="alert" est généralement utilisé pour l’affichage d’un message de statut urgent et qui nécessite une intervention urgente de l’utilisateur, comme :
- La saisie d’une valeur invalide dans un formulaire ;
- L’expiration prochaine de la session ;
- L’interruption de la connexion au serveur ;
- Etc.
Vous pouvez le comparer à l’attribut aria-live="assertive".
Exemple de code utilisant ce rôle :
<div id="alerte-serveur" role="alert"></div>
<script>
// Lorsqu’une erreur survient :document.getElementById('alerte-serveur').innerText = "Erreur : connexion au serveur perdue.";
</script>
Je vous rappelle que le role="alert" ne doit pas déplacer le focus.
Le role="status" est utilisé pour informer l’utilisateur d’un changement de contenu non urgent qui ne nécessite pas d’interruption immédiate de la vocalisation en cours :
- L’avancée ou la fin d’un téléchargement ;
- L’enregistrement d’un fichier ;
- Le nombre de résultats trouvés ;
- L’ajout d’un article au panier ;
- Etc.
Vous pouvez le comparer à l’attribut aria-live="polite".
Exemple de code utilisant ce rôle :
<div id="confirmation-panier" role="status"></div>
<script>
// Lorsque l’utilisateur ajoute un produit :document.getElementById('confirmation-panier').innerText = "Produit ajouté au panier avec succès.";
</script>
Vous recourez au role="log" pour les zones où des informations s’ajoutent de manière séquentielle et chronologique. Contrairement au statut qui remplace souvent le message précédent, le log gère un historique de flux :
- Historiques de discussion d’un chat ;
- Journaux d’erreurs techniques ;
- Flux de notifications ;
- Etc.
Vous pouvez le comparer à l’attribut aria-live="polite".
Exemple de code utilisant ce rôle :
<div id="historique-chat" role="log">
<p>Support : Bonjour, comment puis-je vous aider ?</p>
</div>
<script>
// Lorsqu’un nouveau message arrive :const nouveauMessage = document.createElement("p");
nouveauMessage.innerText = "Utilisateur : J'ai un problème avec ma commande.";
document.getElementById('historique-chat').appendChild(nouveauMessage);
</script>
Le role="progressbar" indique à l’utilisateur qu’un processus est en cours et précise, si c’est possible, son état d’avancement. Contrairement à un simple texte de statut, il fournit des données numériques structurées.
Pour améliorer votre accessibilité, vous le couplez à des attributs de valeur aria-valuenow (valeur actuelle), aria-valuemin (0) et aria-valuemax (100), et vous utilisez un aria-live=”polite” à certains paliers clés (par exemple, tous à 25 %, 50 % et 75 %).
Exemple de code utilisant ce rôle :
<div id="barre-progression"
role="progressbar"
aria-live="polite"
aria-valuenow="0"
aria-valuemin="0"
aria-valuemax="100">
0%
</div>
<script>
// Simulation d’une progression :let barre = document.getElementById('barre-progression');
let progression = 25; // Imaginons que l'on passe à 25%
barre.setAttribute(‘aria-valuenow’, progression);
barre.innerText = progression + “% effectué”;
</script>
