L'accordéon
Un accordéon accessible tient en trois choses : un bouton natif, un état annoncé, un panneau vraiment masqué. Aucun rôle ARIA à inventer. Démo, code, critères RGAA.
4 critères RGAA en jeu
Essayez-le
Oui. Un rapport d'audit doit se relire des mois plus tard, par quelqu'un qui n'était pas là : la capture est ce qui rend le constat vérifiable.
Non. Les critères non applicables sont exclus du calcul : le taux rapporte les critères conformes au nombre de critères réellement applicables.
Le référentiel en impose huit au minimum, et elles doivent couvrir les gabarits et les parcours du site — pas huit pages qui se ressemblent.
Parcourez-le à la tabulation : le focus s’arrête sur chaque intitulé et sur rien d’autre tant que les panneaux sont repliés. Ouvrez-en un, et son contenu entre alors dans l’ordre de tabulation — ni avant, ni après.
Cette démo existe aussi en page autonome.
L’erreur courante
L’accordéon bricolé, c’est un div qui écoute le clic et une classe CSS qui
réduit la hauteur.
<!-- À ne pas faire -->
<div class="titre" onclick="basculer()">Faut-il une capture ?</div>
<div class="panneau replie">
<p>Oui. Un rapport doit se relire des mois plus tard…</p>
</div> /* À ne pas faire : le contenu est toujours là, et toujours focalisable */
.replie {
height: 0;
overflow: hidden;
} Deux fautes, et la seconde est la plus sournoise.
Le div cliquable ne prend pas le focus, ne répond ni à Entrée ni à
Mais le panneau « replié » à hauteur nulle, lui, est toujours là. Ses liens et ses boutons restent dans l’ordre de tabulation : le focus disparaît de l’écran, se promène dans un contenu invisible, puis réapparaît plus bas. C’est le défaut le plus déroutant qui soit pour qui navigue au clavier — et il est invisible à la souris.
Le code, pas à pas
1. Un bouton, dans un titre
<h3>
<button type="button" aria-expanded="false" aria-controls="panneau-preuve">
Faut-il une capture pour chaque non-conformité ?
</button>
</h3>
<div id="panneau-preuve" hidden>
<p>Oui. Un rapport doit se relire des mois plus tard…</p>
</div> Le <button> donne le focus, Entrée, Espace et
l’annonce « bouton » — quatre comportements qu’on ne réécrit pas.
Le bouton se place dans le titre, jamais le titre dans le bouton. Ainsi la
structure de titres reste intacte, et un lecteur d’écran peut sauter d’un
intitulé au suivant par la navigation par titres, sans passer par la tabulation.
Le niveau (h3 ici) suit celui de la section qui contient l’accordéon.
2. L’état : aria-expanded
bouton.setAttribute('aria-expanded', String(ouvert));
panneau.hidden = !ouvert; aria-expanded est l’état, et le lecteur d’écran l’annonce avec le nom :
« Faut-il une capture ?, bouton, réduit ». Le chevron qui tourne dit la même
chose à l’œil — c’est un doublon utile, à condition qu’il soit masqué
(aria-hidden="true") pour ne pas être annoncé en plus.
aria-controls désigne le panneau gouverné. Son effet reste inégal d’un lecteur
à l’autre, mais il ne coûte rien et documente l’intention.
3. Le panneau : hidden, pas une hauteur nulle
<div id="panneau-preuve" hidden>…</div> hidden retire le panneau de l’affichage et de l’ordre de tabulation, en un
attribut. C’est ce qui règle le piège du focus perdu.
Si vous voulez animer l’ouverture, hidden et la transition de hauteur ne se
marient pas d’eux-mêmes. Deux options honnêtes : content-visibility avec transition-behavior: allow-discrete, ou l’élément natif <details> (voir
plus bas). Ce qu’il ne faut pas faire, c’est renoncer à masquer pour pouvoir
animer.
4. Un panneau ouvert n’en ferme aucun autre
Un accordéon laisse ouvrir plusieurs panneaux à la fois. Refermer les autres à chaque ouverture surprend qui vient de lire, et interdit de comparer deux réponses — n’imposez ce comportement que si le besoin l’exige vraiment.
5. <details>, quand il suffit
<details>
<summary>Faut-il une capture pour chaque non-conformité ?</summary>
<p>Oui. Un rapport doit se relire des mois plus tard…</p>
</details> Le navigateur donne alors tout : le focus, le clavier, l’état annoncé, le
masquage réel. C’est la meilleure réponse quand l’apparence par défaut convient
et qu’aucun titre n’est nécessaire — ce qui est plus souvent le cas qu’on ne
croit. Ses limites : le style de <summary> reste contraint, et il n’y a pas de
titre à porter, donc pas de navigation par titres.
Au clavier
| Touche | Effet |
|---|---|
| Tab | Passe à l’intitulé suivant. Le contenu d’un panneau replié n’y figure pas. |
| Entrée / Espace | Ouvre ou ferme le panneau de l’intitulé qui a le focus. |
| Navigation par titres | Saute d’un intitulé à l’autre sans tabuler, parce que le bouton est dans un titre. |
Les flèches ne servent pas ici : contrairement aux onglets, un accordéon est une suite de sections indépendantes, pas un groupe où l’on choisit.
Ce que le lecteur d’écran restitue
Sur l’intitulé : le nom, la nature, l’état — « Faut-il une capture pour chaque non-conformité ?, bouton, réduit ». Après activation, l’état change et se réannonce : « développé ».
Si vous entendez le nom sans l’état, aria-expanded manque ou reste figé. Si
vous n’entendez pas « bouton », c’est un div — et personne ne peut l’ouvrir au
clavier.
Checklist
- Un
<button type="button">, jamais undivcliquable. - Le bouton dans le titre, à un niveau cohérent avec la page.
aria-expandedtenu à jour ;aria-controlsvers le panneau.- Le chevron doublé de l’état, et masqué par
aria-hidden. - Le panneau replié masqué par
hidden— jamais par une hauteur nulle. - Envisagez
<details>avant d’écrire du JavaScript.
Les critères RGAA en jeu
- Critère 7.1 — Compatibilité des scripts
L'état plié ou déplié doit être exposé aux technologies d'assistance : c'est le rôle d'aria-expanded sur le bouton, et un chevron qui tourne ne le remplace pas.
- Critère 7.3 — Contrôle des scripts au clavier
Ouvrir et fermer chaque panneau doit se faire au clavier seul — ce qu'un bouton natif donne, et qu'un div cliquable retire.
- Critère 9.1 — Structure par les titres
Les intitulés d'un accordéon structurent le contenu : ils doivent être des titres de niveau cohérent, le bouton se plaçant dans le titre plutôt que l'inverse.
- Critère 10.8 — Contenus cachés ignorés
Un panneau replié doit être caché pour tout le monde. Réduit à une hauteur nulle, il garde ses liens focalisables et le clavier tombe dans un contenu invisible.
Vérifiez votre composant avec l'extension
Pour aller plus loin
- Critère 7.1 — Compatibilité des scripts et 7.3 — Contrôle au clavier : ce qu’un audit vérifie sur tout composant scripté.
- La modale : l’autre composant qui ouvre et ferme, avec cette fois du focus à conduire.
- « Composant d’interface » au glossaire : la définition qui décide de ce qui relève de ces critères.
Sources
- ARIA APG — Accordion Pattern — le contrat de comportement
- MDN —
<details>— l’alternative native, quand elle suffit - WCAG — Understanding 4.1.2 Name, Role, Value — pourquoi l’état doit être exposé
- GOV.UK Design System — Accordion — quand l’employer, et quand s’en passer