RGAA Lab

Composants accessibles

L'infobulle

Une infobulle décrit un élément qui porte déjà son nom — elle ne le nomme pas. Et l'attribut title n'en est pas une : il n'apparaît jamais au clavier. Démo, code, critères RGAA.

4 critères RGAA en jeu

Essayez-la

Un audit porte sur cent six critères, et son se lit en pourcentage.

Nom accessible
Description résolue depuis aria-describedby
Restitution attendue
(sans nom), bouton, (aucune description)
La bulle
masquée

Atteignez le déclencheur à la tabulation : la bulle s’ouvre au focus, pas seulement au survol. Amenez ensuite la souris dedans — elle reste — puis appuyez sur Échap sans rien bouger : elle se referme.

La fiche d’inspection sous la phrase n’est pas écrite d’avance : elle relit le DOM à chaque bascule, et résout la description en suivant l’aria-describedby du bouton. Remarquez qu’elle reste renseignée quand la bulle est masquée — c’est exactement ce qui la rend audible à la prise de focus.

Cette démo existe aussi en page autonome.

L’erreur courante

L’infobulle qui n’en est pas une : un title, posé sur un élément qui ne prend pas le focus.

<!-- À ne pas faire -->
<span title="Le rapport des critères conformes au nombre de critères applicables">
	taux de conformité
</span>

Ça marche à la souris, et nulle part ailleurs.

Le <span> ne reçoit pas le focus : à la tabulation, il n’y a rien à atteindre et donc rien à afficher. Au doigt, sur un écran tactile, il n’y a pas de survol du tout — l’information n’existe simplement pas. Et l’infobulle native du navigateur, quand elle paraît, s’affiche après un délai, disparaît d’elle-même au bout de quelques secondes, ne se laisse ni styler ni agrandir au zoom texte. Le référentiel ne la sanctionne même pas : un contenu additionnel contrôlé par l’agent utilisateur — le cas particulier du critère 10.13 cite l’attribut title nommément — rend le critère non applicable. Rien à corriger, donc, et rien à lire non plus.

Reste sa restitution. Un lecteur d’écran peut lire un title, mais seulement comme complément d’un élément qui a déjà un rôle — et selon un réglage de verbosité que l’utilisateur peut avoir coupé. Sur un <span> nu, il n’y a souvent rien à entendre. Un attribut qu’on ne peut pas garantir n’est pas un porteur d’information.

Trois variantes, aussi répandues :

  • aria-label sur le déclencheur. La description remplace alors le nom au lieu de le compléter : le bouton s’appelle par son explication, l’intitulé visible disparaît du nom accessible, et la commande vocale qui prononce ce qu’elle voit à l’écran ne trouve plus rien.
  • Un div flottant, sans lien avec le déclencheur. Visible, mais orphelin : rien ne dit à quoi il se rapporte, et l’utilisateur de lecteur d’écran le rencontre — ou pas — quelque part plus loin dans la page.
  • De l’information indispensable dans la bulle. Masquée par défaut, elle échappe à l’impression, à la recherche dans la page, et à qui ne survole jamais rien. Si le contenu est nécessaire, ce n’est pas une infobulle.

Le code, pas à pas

1. Décrire, pas nommer

C’est la distinction dont tout le reste découle. Une infobulle porte un complément sur un élément qui a déjà son nom ; elle ne fournit pas ce nom.

<button type="button" aria-describedby="bulle-taux">
	taux de conformité
</button>

<span id="bulle-taux" role="tooltip" hidden>
	Le rapport des critères conformes au nombre de critères applicables.
</span>

Le nom vient de l’intitulé visible du bouton, la description de la bulle. aria-labelledby ou aria-label à la place feraient l’inverse : ils écraseraient l’intitulé, et le critère 7.1 demande précisément que le nom accessible contienne au moins l’intitulé visible.

Deux remarques sur role="tooltip". Il n’ajoute presque rien à la restitution — c’est aria-describedby qui fait passer le texte ; il documente l’intention, et ne coûte rien. En revanche il engage : le motif ARIA n’y prévoit aucun élément interactif. Un lien dans la bulle en fait autre chose.

Et un point qui surprend : le passage référencé compte même masqué. Le calcul de la description accessible n’écarte pas un élément caché quand il est directement désigné par aria-describedby — c’est pourquoi le texte est annoncé à la prise de focus, sans que l’affichage visuel ait à intervenir.

2. Un déclencheur qui peut recevoir le focus

<button type="button" aria-describedby="bulle-taux">taux de conformité</button>

Pas de <span>, pas de <div tabindex="0"> : le premier n’est pas atteignable, le second est atteignable mais muet — un div focalisable n’annonce ni nature ni fonction.

Quand l’infobulle décrit un champ de formulaire, le déclencheur est le champ lui-même, avec le même aria-describedby : n’ajoutez pas un point d’interrogation à côté, qui ferait un arrêt de tabulation de plus pour la même information. Si vous tenez au bouton d’aide, donnez-lui un nom qui se suffit — « Aide sur le taux de conformité », pas « ? ».

3. Survol et focus, sur le groupe

// Le groupe contient le déclencheur ET la bulle.
groupe.addEventListener('pointerenter', afficher);
groupe.addEventListener('pointerleave', masquer);

declencheur.addEventListener('focus', afficher);
declencheur.addEventListener('blur', masquer);

Les écouteurs de pointeur se posent sur le groupe, pas sur le déclencheur : c’est ce qui permet à la souris de descendre dans la bulle sans la faire disparaître sous elle (test 10.13.2). Et il ne doit y avoir aucun vide entre les deux — si vous décalez la bulle, faites-le avec un rembourrage qui lui appartient, pas avec une marge qui creuse un trou.

Le couple focus/blur est ce qui répond au critère 12.11 : sans lui, l’infobulle n’existe qu’à la souris.

4. Échap referme, sans que rien ne bouge

window.addEventListener('keydown', (evenement) => {
	if (evenement.key !== 'Escape' || !visible) return;
	evenement.preventDefault();
	masquer();
});

L’écouteur est sur la fenêtre, et c’est délibéré : à la souris, aucun élément n’a le focus quand la bulle s’affiche — posé sur le déclencheur, il ne se déclencherait jamais. C’est le test 10.13.1, qui demande de pouvoir masquer sans déplacer le focus ni le pointeur.

Le refus ne vaut que pour la visite en cours : une fois le pointeur et le focus sortis, oubliez-le, sinon une bulle refermée une fois ne reparaîtrait plus.

5. En avez-vous besoin ?

Presque à chaque fois, la réponse honnête est non.

Si le texte est utile, il se met sous le champ ou à côté de l’intitulé, en clair, relié par le même aria-describedby — le mécanisme ARIA est identique, il ne lui manque que le masquage. Si le texte est long, ce n’est plus une infobulle. S’il contient un lien ou un bouton, c’est un panneau à ouvrir, avec aria-expanded sur son déclencheur et un focus qu’on peut y conduire.

L’infobulle ne garde qu’un usage étroit : un rappel court, secondaire, pour un lecteur qui a déjà tout ce qu’il lui faut sans elle.

Au clavier

ToucheEffet
TabAmène le focus sur le déclencheur : la bulle s’affiche, et le focus reste sur le déclencheur.
Tab (à nouveau)Emmène le focus à l’élément suivant ; la bulle se referme derrière.
ÉchapReferme la bulle. Le focus ne bouge pas, le pointeur non plus.
Entrée / EspaceAffiche ou referme la bulle — le même geste que le clic, et la seule voie sur un écran tactile.

Aucune touche n’entre dans la bulle : il n’y a rien à y atteindre. Si vous avez besoin d’y tabuler, ce n’est pas une infobulle.

Ce que le lecteur d’écran restitue

Sur le déclencheur : le nom, la nature, puis la description — de l’ordre de « taux de conformité, bouton, Le rapport des critères conformes au nombre de critères applicables ». La formulation change d’un lecteur à l’autre, et la description arrive parfois après un bref délai ; les trois informations, elles, ne changent pas.

Si vous n’entendez que « taux de conformité, bouton », l’aria-describedby ne pointe sur rien : vérifiez que l’id existe bien dans la page. Si vous entendez la description à la place de l’intitulé, c’est aria-label qui a été employé — l’infobulle nomme au lieu de décrire. Et si la souris affiche une bulle dont la tabulation ne dit rien, le texte est resté dans un title ou dans un div sans lien avec le déclencheur.

Checklist

  • aria-describedby du déclencheur vers la bulle — jamais aria-label.
  • Un déclencheur focalisable : un <button>, ou le champ que la bulle décrit.
  • La bulle s’ouvre à la prise de focus autant qu’au survol.
  • Survolable sans fuir : déclencheur et bulle dans un même groupe, sans vide entre eux.
  • Échap la referme sans déplacer le focus ni le pointeur.
  • Rien d’interactif dedans, rien d’indispensable non plus.
  • title seul n’est pas une infobulle accessible.

Les critères RGAA en jeu

Vérifiez votre composant avec l'extension

Pour aller plus loin

Sources