RGAA Lab

Composants accessibles

Les régions et points de repère

Cinq balises donnent à une page ses régions : header, nav, main, aside, footer. Un lecteur d'écran en dresse alors la liste et saute de l'une à l'autre — ce qu'aucune classe CSS ne fera jamais. Démo, code, critères RGAA.

3 critères RGAA en jeu

Essayez-le

Balisée en div

Le même encadré, en <div>. À l’œil, rien ne les sépare — dans la liste, celui-ci manque.

Le bouton dresse la liste des régions telle qu’un lecteur d’écran la donne.

Les deux cartes ci-dessus sont identiques à l’œil ; une seule est un <aside>. Demandez la liste des régions : celle en div n’y figure pas, et la page dont vous lisez ces lignes s’y montre telle qu’un lecteur d’écran la voit. Chaque bouton « Aller à » déplace le focus dans la région : l’équivalent au clavier du raccourci de région, qui lui déplace le curseur de lecture et non le focus.

Cette démo existe aussi en page autonome.

L’erreur courante

Une page dont toute la structure est faite de div et de classes CSS.

<!-- À ne pas faire -->
<div class="header"></div>
<div class="nav"></div>
<div class="content"></div>
<div class="footer"></div>

Le rendu est le bon, la maquette est respectée, et la page n’a aucune région. Ce que cela coûte se mesure en pressions de touche : sans <main>, il n’y a pas de raccourci qui saute au contenu, et chaque changement de page se paye d’un parcours complet de l’en-tête et du menu. La liste des régions, que les lecteurs d’écran proposent, est simplement vide.

Quatre des six conditions du test 9.2.1 nomment une balise — en-tête en <header>, navigations en <nav>, contenu principal en <main>, pied de page en <footer> — et cette page les échoue toutes les quatre en même temps. La cinquième, le <main> visible unique, tombe avec elles : sans <main>, il n’y en a pas un seul.

Trois variantes plus discrètes, et qui passent souvent la relecture :

  • <main role="main">. Le rôle est déjà là, l’attribut ne l’ajoute pas. Ce n’est pas une non-conformité, c’est du bruit — et le signe que le rôle implicite n’est pas connu. Le jour où quelqu’un écrit role="main" sur un <div> voisin, la page a deux zones de contenu principal et plus personne ne sait laquelle est la bonne.
  • Deux <nav> sans nom. La liste des régions annonce « navigation, navigation » : on sait qu’il y a deux menus, jamais lequel choisir.
  • Le <header> d’une carte pris pour celui de la page. Sous un <article> ou une <section>, <header> n’est plus la zone d’en-tête du document — le rôle disparaît, et personne ne le voit puisque rien ne change à l’écran.

Le code, pas à pas

1. Les balises, et rien à déclarer

<header></header>
<nav aria-label="Principale"></nav>
<main></main>
<aside aria-label="Sur le même sujet"></aside>
<footer></footer>

Aucun role n’est écrit, et pourtant les cinq régions existent : banner, navigation, main, complementary, contentinfo. C’est le rôle implicite de chaque balise, et il ne s’écrit pas deux fois.

Le référentiel n’en exige que quatre — <header>, <nav>, <main>, <footer> sont ce que le test 9.2.1 énumère. <aside> n’y figure pas : c’est une bonne pratique HTML pour les contenus adjacents, pas une obligation RGAA.

2. Un seul <main> visible

C’est la condition qu’on casse le plus souvent sans le vouloir : le test 9.2.1 demande que « la structure du document utilise une balise <main> visible unique ». Visible est le mot qui compte. Une application qui garde plusieurs vues dans le DOM peut avoir plusieurs <main>, à condition qu’un seul soit affiché à la fois.

En pratique, deux cas produisent le doublon :

<!-- À ne pas faire : un composant qui porte son propre <main> -->
<main>
	<article>
		<main></main>
	</article>
</main>

Une mise en page qui pose le <main>, et un composant réutilisable qui en pose un second. Ou un système d’onglets dont les panneaux inactifs sont repoussés hors écran plutôt que masqués : ils restent visibles au sens du test, et la page a autant de <main> que d’onglets.

3. <nav> est réservé, et se nomme quand il se répète

Le test 9.2.1 pose deux exigences sur cette balise : les navigations principales et secondaires sont en <nav>, et <nav> est réservé à cela. Une rangée de liens vers les réseaux sociaux ou une liste de mots-clés enveloppées dans un <nav> échouent au second point autant qu’un menu en <div> échoue au premier.

Dès qu’il y en a plusieurs, le glossaire du référentiel indique la marche à suivre : « Lorsqu’il y a plusieurs rôles WAI-ARIA navigation, il peut être utile de les différencier en précisant un nom à chacune des zones via l’attribut WAI-ARIA aria-label ou aria-labelledby. »

<nav aria-label="Principale"></nav>
<nav aria-label="Fil d’Ariane"></nav>
<nav aria-label="Pagination des résultats"></nav>

Le nom ne répète pas le rôle. aria-label="Navigation principale" s’annonce « Navigation principale, navigation » : le mot est dit deux fois, et il ne reste qu’un mot utile sur trois.

Si un titre visible nomme déjà la zone, aria-labelledby vaut mieux que aria-label : le nom reste alors le même à l’œil et à l’oreille, et une traduction ne peut pas oublier l’attribut.

4. <header> et <footer> changent de rôle selon l’endroit

<header></header>
<!-- rôle banner : au premier niveau -->

<main>
	<article>
		<header></header>
		<!-- aucun rôle : c'est l'en-tête de l'article -->
	</article>
</main>

Sous un <article>, un <aside>, un <main>, un <nav> ou une <section>, <header> et <footer> perdent leur rôle de région. Le glossaire prévient du même piège dans l’autre sens : « Attention à ne pas confondre cette zone d’en-tête, unique dans le site, avec tout contenu pouvant être balisé en HTML5 avec l’élément <header>. »

C’est une règle utile, pas une gêne : elle évite qu’une page de vingt articles déclare vingt bannières.

5. Les régions ne remplacent pas le lien d’évitement

Le glossaire est explicite, et va à l’encontre de ce qu’on suppose : « Si la plupart des lecteurs d’écran mettent à disposition ces fonctionnalités, les navigateurs n’ont pas encore proposé de fonctionnalité de navigation dédiée pour les utilisateurs qui ne peuvent pas utiliser la souris. La mise en place des liens d’évitement reste donc à privilégier par rapport aux landmarks. »

Les régions servent qui a un lecteur d’écran. Qui navigue au clavier sans lecteur d’écran n’a aucun raccourci de région dans son navigateur, et ne dispose que de la tabulation. Le critère 12.7 exige donc un lien d’évitement en plus, et c’est le <main> qui lui donne sa cible :

<a href="#contenu" class="evitement">Aller au contenu</a><main id="contenu" tabindex="-1"></main>

6. Avant d’ajouter une région : la liste doit rester lisible

role="region" sur une <section> nommée est licite, et fabrique une entrée de plus dans la liste. Vingt entrées ne valent pas mieux qu’aucune : la liste des régions vaut par sa brièveté, comme une table des matières.

La question à se poser est celle-ci : cette zone est-elle un endroit où quelqu’un voudrait sauter directement ? Si la réponse est non, une <section> et un titre <h2> suffisent — et le titre, lui, est cherché par la navigation par titres, qui reste le raccourci le plus employé.

Au clavier

Ce composant n’est pas interactif : les régions ne prennent pas le focus et ne figurent pas dans l’ordre de tabulation. Elles s’atteignent par les raccourcis des lecteurs d’écran, et par eux seuls.

ToucheEffet
TabRien de particulier. Aucun navigateur n’offre de saut de région : c’est ce que constate le glossaire du référentiel, et pourquoi le lien d’évitement reste nécessaire.
D / Maj + D (NVDA)Va à la région suivante ou précédente. Le curseur de lecture se pose au début de la région.
R / Maj + R (JAWS)Le même déplacement, d’une région à la suivante ou à la précédente.
VO + U (VoiceOver)Ouvre le rotor, où les points de repère forment une liste ; en choisir un y déplace le curseur.

Ce que le lecteur d’écran restitue

En entrant dans une région : sa nature, et son nom s’il y en a un — de l’ordre de « Principale, navigation », puis « Fil d’Ariane, navigation ». En sortant, la fin de la région est annoncée. La formulation varie d’un lecteur à l’autre, pas les informations : une nature, un nom, une entrée et une sortie.

Le diagnostic se fait mieux par la liste des régions que par la lecture continue. Si elle est vide, tout est en div. Si elle affiche deux fois « navigation » sans rien qui les sépare, les aria-label manquent. Si le raccourci de région ne s’arrête jamais sur le contenu, il n’y a pas de <main> — ou il y en a deux, et l’outil s’arrête sur le mauvais.

Checklist

  • <header>, <nav>, <main>, <footer> — les quatre que le test 9.2.1 énumère.
  • Un seul <main> visible dans la page.
  • <nav> réservé aux navigations principales et secondaires, et à rien d’autre.
  • Chaque <nav> nommé dès qu’il y en a plusieurs, sans répéter le mot « navigation ».
  • Aucun role redondant sur une balise qui porte déjà le sien.
  • Un lien d’évitement vers le <main> en plus des régions, jamais à leur place.
  • La liste des régions relue en entier : si elle est longue, elle ne sert plus.

Les critères RGAA en jeu

Vérifiez votre composant avec l'extension

Pour aller plus loin

Sources