Courant Mis à jour : 2026-05

aria-label et aria-labelledby : quand les utiliser, et quand ils ne servent à rien

Ajouter un aria-label ne suffit pas toujours. Ce que ça change concrètement pour un lecteur d'écran, et les cas où le label est ignoré sans qu'aucune erreur ne soit signalée.

Table des matières

aria-label et aria-labelledby servent à nommer un élément. Pas à lui donner un rôle. Pas à le rendre accessible par magie. Nommer un élément sans rôle ne produit rien. Et nommer un élément qui n’en a pas besoin crée du bruit.

Ce que fait concrètement un aria-label

Un lecteur d’écran annonce un élément en combinant deux informations : son rôle et son nom accessible. Le rôle vient du HTML (<nav> = “navigation”, <button> = “bouton”). Le nom accessible, c’est le contenu texte de l’élément, ou la valeur d’aria-label ou aria-labelledby si ces attributs sont présents.

Avec NVDA + Firefox, naviguer vers un <nav> sans label produit :

"navigation"

Avec aria-label="Menu principal" :

"Menu principal, navigation"

Le nom passe en premier, le rôle suit. C’est l’ordre d’annonce standard. L’utilisateur sait immédiatement de quelle navigation il s’agit, sans avoir à en parcourir le contenu.

La règle de base : label uniquement si le rôle ne suffit pas

Un seul <nav> sur la page : le rôle suffit. L’utilisateur sait qu’il y a une navigation, et il n’y en a qu’une. Ajouter aria-label="Navigation" ne fait qu’annoncer “Navigation, navigation” sur certains lecteurs d’écran. C’est redondant.

Plusieurs <nav> sur la page : là, le label devient indispensable. Sans lui, l’utilisateur entend “navigation” deux fois, sans moyen de distinguer l’une de l’autre.

Le principe s’applique à tous les éléments de type landmark :

ÉlémentLabel utile si…
<nav>Plusieurs <nav> sur la page
<aside>Plusieurs <aside> sur la page
<header>, <footer>Utilisés hors contexte <body> (donc sans rôle banner / contentinfo)
<main>Contenu qui change dynamiquement (cas rare)
<form>Plusieurs formulaires, ou formulaire sans titre visible
<dialog>Toujours (obligatoire pour que la modale soit annoncée correctement)
<section>Toujours (voir section suivante)

Le cas particulier de <section>

<section> sans label accessible n’est pas exposée comme landmark. Le lecteur d’écran la traite comme un <div> générique : aucune annonce à l’entrée, aucune navigation possible via les raccourcis.

Avec aria-label ou aria-labelledby, <section> acquiert le rôle implicite region et devient navigable via la touche R sous NVDA et JAWS.

<!-- Ignorée comme landmark, traitée comme un div -->
<section>
  <h2>Nos services</h2>
  ...
</section>

<!-- Rôle "region" actif, navigable au clavier -->
<section aria-labelledby="titre-services">
  <h2 id="titre-services">Nos services</h2>
  ...
</section>

La deuxième forme est préférable à aria-label quand un titre visible existe déjà : aria-labelledby pointe vers ce titre et évite de dupliquer le texte.

aria-label vs aria-labelledby : lequel choisir

aria-label contient directement le texte du nom accessible. aria-labelledby pointe vers un élément existant dans le DOM via son id.

<!-- aria-label : texte directement dans l'attribut -->
<nav aria-label="Navigation secondaire">...</nav>

<!-- aria-labelledby : texte récupéré depuis un élément existant -->
<section aria-labelledby="titre-contact">
  <h2 id="titre-contact">Nous contacter</h2>
  ...
</section>

aria-labelledby est à privilégier quand un titre visible peut servir de référence : le nom accessible et le contenu visuel restent synchronisés, et le titre n’est pas répété dans le code. aria-label s’utilise quand aucun texte visible ne convient, par exemple pour un bouton icône ou une navigation dont le titre n’est pas affiché.

Les cas où le label est ignoré

C’est ici que les erreurs silencieuses se produisent. Aucune alerte, aucun message d’erreur dans les outils d’audit, mais le label n’est pas lu.

Un élément sans rôle sémantique significatif

aria-label sur un <div> ou un <span> sans attribut role : ignoré. L’élément n’a pas de point d’annonce.

<!-- Ignoré : div sans rôle -->
<div aria-label="Section actualités">...</div>

<!-- Fonctionnel : rôle explicite -->
<div role="region" aria-label="Actualités">...</div>

Une cible masquée avec display: none ou visibility: hidden

aria-labelledby récupère le contenu d’un élément référencé. Si cet élément est masqué via display: none ou visibility: hidden, son contenu texte n’est pas accessible à l’arbre d’accessibilité : le label est vide.

Le masquage .sr-only (clip technique) fonctionne, lui : l’élément est retiré visuellement mais reste dans l’arbre d’accessibilité.

/* Masquage qui coupe l'accès : aria-labelledby ne peut pas récupérer ce texte */
.masque { display: none; }

/* Masquage qui préserve l'accès */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

Un id absent, mal orthographié ou dupliqué

aria-labelledby ne produit aucune erreur si l’id référencé n’existe pas. Le label est simplement ignoré. Un id dupliqué dans la page (erreur fréquente dans les composants réutilisables) produit le même résultat : le comportement est indéfini.

<!-- id="titre-nav" inexistant dans le DOM : label silencieux -->
<nav aria-labelledby="titre-nav">...</nav>

<!-- Fonctionne -->
<nav aria-labelledby="titre-navigation-principale">
  <h2 id="titre-navigation-principale" class="sr-only">Navigation principale</h2>
  ...
</nav>

aria-hidden="true" sur la cible

Si l’élément référencé par aria-labelledby porte aria-hidden="true", son contenu est masqué à l’arbre d’accessibilité : le label est ignoré.

Tableau récapitulatif

Situationaria-label lu ?Raison
<nav aria-label="..."> (un seul nav)Oui, mais inutileRedondant avec le rôle
<nav aria-label="..."> (plusieurs nav)OuiDisambiguïsation nécessaire
<section aria-label="...">OuiCrée le rôle region
<section> sans labelNon annoncéePas de rôle landmark
<div aria-label="..."> sans roleNonPas de point d’annonce
aria-labelledbydisplay: noneNonÉlément absent de l’arbre
aria-labelledby.sr-onlyOuiAccessible mais masqué visuellement
aria-labelledbyid introuvableNonRéférence invalide, silencieuse
aria-labelledbyaria-hidden="true"NonExclu de l’arbre d’accessibilité

En pratique pour un audit RGAA

Le critère 12.6 demande que chaque groupe de liens (navigation) soit identifié. Les vérifications à faire :

  1. Compter les <nav> sur la page. Si plusieurs : vérifier que chacun a un label distinct.
  2. Sur les <section>, vérifier la présence d’un aria-label ou aria-labelledby. Sans ça, la section n’est pas un landmark.
  3. Pour chaque aria-labelledby, vérifier que l’id référencé existe, est unique, et que l’élément ciblé n’est ni display: none ni aria-hidden.
  4. Tester avec NVDA (Firefox) et VoiceOver (Safari) : l’annonce “Nom, rôle” doit être explicite et non redondante.

Les outils automatiques (axe, WAVE) détectent les <nav> sans label quand il y en a plusieurs. Ils ne détectent pas les labels silencieux dus à une cible mal masquée ou un id dupliqué. Ces vérifications sont manuelles.

La lettre de l'Atelier A11Y

Ressources pédagogiques, critères RGAA commentés et retours de terrain : une lettre mensuelle pour progresser sur l'accessibilité numérique, sans jargon.

  • Nouveaux articles et ressources pédagogiques
  • Critères RGAA décortiqués avec des exemples concrets
  • Bonnes pratiques et retours d'expérience terrain
S'abonner à la newsletter (s'ouvre dans un nouvel onglet)

Gratuit. Désabonnement possible à tout moment.