Skip to Content

Chapitre 5.2 — L’arbre d’accessibilité

⏱️ TL;DR — À partir de ton DOM, le navigateur construit un arbre d’accessibilité (accessibility tree, ou AX tree) : une version simplifiée où chaque nœud porte un nom, un rôle et une valeur/état. C’est cet arbre — pas tes pixels, pas ton CSS — que consomment les technologies d’assistance. Certains éléments y entrent (un <button>, un <h1>), d’autres en sont retirés (display:none, aria-hidden="true", une <div> purement décorative). La bonne nouvelle : tu peux l’inspecter dans les DevTools. Arrête de deviner ce que « voit » un lecteur d’écran — regarde l’arbre.

🎯 Objectifs

  • Expliquer comment le navigateur passe du DOM à l’arbre d’accessibilité.
  • Savoir ce qui est exposé dans l’arbre et ce qui en est retiré.
  • Lister ce qui modifie l’arbre (balises, ARIA, CSS display/visibility).
  • Inspecter l’arbre dans les DevTools de Chrome et de Firefox.
  • Adopter le réflexe « j’inspecte » au lieu de « je suppose ».

Du DOM à l’arbre d’accessibilité

Ton navigateur maintient plusieurs représentations de la page en parallèle. Le DOM sert au rendu et au JavaScript. À côté, il calcule un arbre d’accessibilité : une structure dérivée, plus pauvre, destinée aux API d’accessibilité du système d’exploitation. Les technologies d’assistance (lecteur d’écran, commande vocale, afficheur braille) ne lisent pas ton DOM directement — elles interrogent cet arbre via ces API.

Chaque nœud de l’arbre expose au minimum :

  • un rôle (role) — la nature de l’élément : button, link, heading, checkbox, navigation
  • un nom accessible (name) — le texte qui l’identifie : « Envoyer », « Accueil », « Se souvenir de moi »…
  • une valeur / des états (value / states) — coché ou non, développé ou replié, désactivé, requis, sa position dans un ensemble…

C’est le triptyque nom / rôle / valeur (critère 4.1.2), qu’on détaille au chapitre 5.3. Retiens ici l’idée-clé : l’arbre est la seule chose que la technologie d’assistance connaît de ta page.

Ce qui entre, ce qui est retiré

L’arbre n’est pas une copie 1:1 du DOM. Le navigateur filtre et transforme.

Sont exposés (avec un rôle utile) : les éléments interactifs et sémantiques natifs (<a href>, <button>, <input>, <nav>, <h1><h6>, <ul>/<li>, <table>…), et le texte qu’ils contiennent.

Sont retirés (absents de l’arbre, donc invisibles pour la technologie d’assistance) :

  • tout ce qui est masqué par display:none ou l’attribut hidden ;
  • tout ce qui porte aria-hidden="true" (l’élément et ses descendants) ;
  • souvent, les éléments purement présentationnels sans contenu textuel (une <div> vide de mise en page).

Sont « aplatis / neutres » : une <div> ou un <span> sans rôle apparaissent au mieux comme des conteneurs génériques sans sémantique — ils ne s’annoncent pas comme quoi que ce soit d’interactif. C’est toute la différence entre un vrai <button> (rôle button, focusable, annoncé) et une <div class="btn"> (conteneur muet).

Côté utilisateur — Ce filtrage a une conséquence brutale : si ton bouton « Supprimer » est une <div> stylée sans rôle, il n’existe tout simplement pas dans l’arbre d’accessibilité. L’utilisateur de lecteur d’écran ne l’entend pas, ne peut pas l’atteindre, ne sait même pas qu’il est là. Ce n’est pas « mal annoncé » : c’est absent. Le design le montre, l’arbre l’ignore.

Ce qui modifie l’arbre

Quatre leviers changent l’arbre d’accessibilité. Les connaître, c’est piloter ce que l’utilisateur perçoit :

  1. Le choix de la balise. <button> vs <div>, <nav> vs <div>, <h2> vs <p> en gras : la balise native fixe le rôle. C’est le levier le plus puissant, et le premier à corriger.
  2. Les attributs ARIA. role="..." remplace le rôle, aria-label/aria-labelledby fixent le nom, aria-expanded/aria-checked renseignent l’état, aria-hidden="true" retire le nœud de l’arbre. Puissant et dangereux — voir Partie 6.
  3. Le CSS display et visibility. display:none et visibility:hidden retirent l’élément de l’arbre (il n’est plus perçu). En revanche, déplacer un élément hors de l’écran par positionnement (technique sr-only) le garde dans l’arbre : masqué à l’œil, lu par le lecteur. On creuse ça au chapitre 5.5.
  4. Le contenu textuel et les alternatives. Le texte visible, un alt d’image, un <label> associé : ils fournissent le nom des nœuds.

⚠️ Piège — Le CSS n’est pas neutre pour l’a11y. Beaucoup croient que « c’est juste du visuel ». Faux : display:none supprime l’élément de l’arbre d’accessibilité, exactement comme il le retire du rendu. À l’inverse, opacity:0 ou un z-index négatif ne le retirent pas de l’arbre — l’élément reste lu alors qu’il est invisible. Choisis la technique de masquage en fonction de ce que tu veux pour l’arbre, pas seulement pour l’œil.

Inspecter l’arbre dans les DevTools

Tu n’as pas à imaginer l’arbre : les navigateurs te le montrent.

Chrome (et Edge) :

  1. Ouvre les DevTools (F12), onglet Elements.
  2. Sélectionne un élément, puis va dans le panneau latéral Accessibility.
  3. Tu y vois le Computed Properties : le rôle calculé, le nom accessible et d’où il vient (le fameux calcul du nom), et les états. La section Accessibility Tree (que tu peux activer en pleine page via « Enable full-page accessibility tree ») affiche l’arbre complet.

Firefox :

  1. Ouvre les DevTools, onglet Accessibilité (Accessibility Inspector). Active-le si besoin.
  2. Tu obtiens l’arbre complet, et pour chaque nœud son rôle et son nom.
  3. Le menu « Check for issues » signale des problèmes courants (contraste, texte alternatif manquant, etc.).

Le réflexe pro : après avoir codé un composant, sélectionne-le et lis son nœud dans l’arbre. Rôle attendu ? Nom correct et non vide ? États présents ? Si le nom est vide ou le rôle « generic », tu as ta réponse avant même de lancer un lecteur d’écran.

💡 RéflexeInspecte l’arbre, ne devine pas. Face à un doute (« est-ce que mon icône-bouton a un nom ? », « est-ce que ce aria-hidden a bien retiré le bloc ? »), ouvre le panneau Accessibility et regarde le nœud. C’est plus rapide, plus fiable et plus pédagogique que de raisonner de tête. L’arbre est la source de vérité ; les DevTools te la donnent gratuitement.

🧭 Sur A11yLearn — Sur le tableau de bord d’A11yLearn, on avait une carte « Reprendre le cours » dont l’action était portée par une <div onclick> avec une icône « play ». En inspectant l’arbre dans Chrome, verdict sans appel : nœud de rôle generic, nom accessible vide. Invisible et innommé pour le lecteur. On l’a remplacée par un <button> avec un texte accessible « Reprendre : Introduction à React » — et l’arbre affiche désormais rôle button, nom correct. Un aller-retour de deux minutes dans les DevTools, un bug d’accessibilité éliminé.

✏️ Exercices

Exercice 1 — Prédis l’arbre. Pour chacun, dis s’il apparaît dans l’arbre d’accessibilité et avec quel rôle approximatif : (a) <button>Envoyer</button>, (b) une <div class="card"> de mise en page, (c) un <span aria-hidden="true">★</span>, (d) un <img src="logo.png" alt="A11yLearn">.

✅ Solution

(a) Présent, rôle button, nom « Envoyer ». (b) Présent mais neutre : conteneur générique sans rôle sémantique (souvent ignoré comme simple regroupement). (c) Retiré : aria-hidden="true" sort le nœud (et ses descendants) de l’arbre — parfait pour une étoile décorative. (d) Présent, rôle image, nom « A11yLearn » fourni par l’alt. Vérifie chaque cas dans le panneau Accessibility plutôt que de te fier à ta mémoire.

Exercice 2 — Le CSS traître. Un dev masque un message d’erreur avec opacity:0 tant qu’il n’y a pas d’erreur, puis le passe à opacity:1. Un testeur au lecteur d’écran se plaint d’entendre « Champ requis » alors que rien n’est affiché. Explique et propose un correctif.

✅ Solution

opacity:0 masque l’élément à l’œil mais ne le retire pas de l’arbre d’accessibilité : le message reste lu. D’où le décalage entre ce qui est vu (rien) et ce qui est entendu (« Champ requis »). Correctif : masquer réellement avec display:none ou l’attribut hidden quand il n’y a pas d’erreur (l’élément quitte l’arbre), et ne le rendre qu’au moment où l’erreur existe. Vérifie ensuite dans les DevTools que le nœud disparaît bien de l’arbre à l’état « pas d’erreur ».

🧠 Quiz de révision

1. Qu’est-ce que l’arbre d’accessibilité ?

Une représentation simplifiée du DOM que le navigateur calcule pour les API d’accessibilité de l’OS. Chaque nœud porte un nom, un rôle et une valeur/état. C’est cet arbre — pas les pixels ni le CSS — que consomment les technologies d’assistance.

2. Cite deux choses qui retirent un élément de l’arbre.

display:none (et l’attribut hidden), ainsi que aria-hidden="true" — qui retire le nœud et ses descendants. visibility:hidden le retire aussi. En revanche, opacity:0 ou un positionnement hors-écran ne le retirent pas : l’élément reste dans l’arbre.

3. Une <div class="btn" onclick> apparaît-elle comme un bouton dans l’arbre ?

Non. Sans rôle déclaré, une <div> est un conteneur générique : pas de rôle button, pas de nom garanti, pas de focus. Elle est au mieux muette, au pire absente. Un vrai <button> (ou un role="button" correctement outillé) est requis pour exister comme bouton dans l’arbre.

4. Comment inspecter le nom et le rôle d’un élément dans Chrome ?

DevTools → onglet Elements → sélectionner l’élément → panneau Accessibility. On y lit le rôle calculé, le nom accessible et son origine, et les états. Firefox propose l’onglet Accessibilité avec l’arbre complet.

5. Pourquoi vaut-il mieux inspecter l’arbre que deviner ?

Parce que l’arbre est la source de vérité que la technologie d’assistance consomme réellement. Deviner mène à des erreurs (nom vide, rôle generic, élément retiré sans le vouloir) ; inspecter le panneau Accessibility donne la réponse exacte en quelques secondes, avant même de lancer un lecteur d’écran.


Chapitre suivant : Nom, rôle, valeur — le triptyque 4.1.2 qui structure tout l’arbre, et surtout comment le nom accessible se calcule.

Last updated on