# « Form elements must have labels » : l’erreur axe qui persiste malgré un label

> Le label est bien là, visuellement collé au champ. Et pourtant axe DevTools continue de signaler l'absence d'étiquette. La raison est purement technique.

- Auteur : WordPress Développement
- Publié le : 2021-10-12
- Mis à jour le : 2021-10-12
- Catégorie : Accessibilité
- URL : https://www.wpmoderne.fr/accessibilite/form-elements-must-have-labels-erreur-axe-persiste/

## L’essentiel

- Un label visuellement proche n'est pas toujours associé techniquement
- for et id doivent correspondre exactement, caractère pour caractère
- aria-label ou aria-labelledby sont des alternatives valables si le for est impossible

« Form elements must have labels » : l'extension axe DevTools affiche cette erreur sur un champ de recherche qui possède pourtant, à l'écran, un texte « Rechercher » juste au-dessus. Le développeur qui découvre ce message pour la première fois soupçonne un bug de l'outil. Ce n'est presque jamais le cas : axe ne juge pas la présence visuelle d'un texte, mais l'existence d'une association programmatique entre ce texte et le champ concerné.

## Symptôme

Le code source du champ ressemble à ceci :

```
<span class="libelle-champ">Rechercher</span>
<input type="search" name="s" placeholder="Tapez votre recherche">
```

Visuellement, tout est parfaitement lisible : le texte « Rechercher » précède le champ, le style CSS les rapproche visuellement. Mais un lecteur d'écran qui atteint ce champ n'annonce que « champ de recherche », sans jamais mentionner « Rechercher », car aucune relation technique ne relie le `<span>` au champ `<input>`.

## Diagnostic

> L'essentiel à retenir : Un label visuellement proche n'est pas toujours associé techniquement ; for et id doivent correspondre exactement, caractère pour caractère ; aria-label ou aria-labelledby sont des alternatives valables si le for est impossible

Un lecteur d'écran, comme un outil d'audit automatisé, ne peut pas déduire une relation entre deux éléments à partir de leur seule proximité visuelle dans le CSS. Il lui faut une relation explicite dans le HTML : soit un véritable élément `<label>` avec un attribut `for` pointant vers l'`id` exact du champ, soit un attribut `aria-label` ou `aria-labelledby` directement posé sur le champ. Un `<span>` stylé pour ressembler à un label n'en est pas un aux yeux de la technologie d'assistance : c'est un texte flottant, sans lien programmatique avec quoi que ce soit.

La confusion vient souvent d'un habillage CSS trop poussé, où un designer ou développeur a recréé visuellement l'apparence d'un label sans utiliser la véritable balise sémantique, parfois pour contourner des contraintes de mise en page héritées d'un framework CSS.

## Correctif

La correction la plus robuste consiste à utiliser un véritable `<label>` associé par `for`/`id` :

```
<label for="recherche-site">Rechercher</label>
<input type="search" id="recherche-site" name="s" placeholder="Tapez votre recherche">
```

L'attribut `for` doit correspondre exactement à l'`id` du champ, caractère pour caractère, y compris la casse. Une erreur fréquente consiste à générer dynamiquement les `id` côté PHP (via un compteur de boucle sur un widget de recherche répété) sans s'assurer que le `for` du label suit la même génération, ce qui provoque une désynchronisation silencieuse dès le deuxième champ affiché sur la page.

Lorsqu'un vrai `<label>` n'est techniquement pas envisageable (composant tiers qui génère son propre balisage, contrainte de plugin WooCommerce), une alternative valable consiste à poser `aria-label` directement sur le champ :

```
<input type="search" name="s" aria-label="Rechercher sur le site" placeholder="Tapez votre recherche">
```

## Vérification

Après correction, relancer axe DevTools doit faire disparaître l'anomalie. Un second test, plus fiable encore, consiste à activer un lecteur d'écran (NVDA ou VoiceOver) et vérifier que le nom annoncé lors de l'arrivée sur le champ correspond bien au libellé attendu, et non simplement au type de champ générique.

## Cas particuliers à surveiller

- Les champs générés par des blocs Gutenberg de formulaire, où l'`id` peut être dupliqué si le même bloc est utilisé deux fois sur la même page.
- Les champs de recherche WooCommerce natifs, dont le `placeholder` seul ne suffit jamais comme étiquette, car il disparaît dès la saisie du premier caractère.
- Les formulaires générés par des extensions tierces (Contact Form 7, Gravity Forms) où le générateur visuel peut, selon la configuration, oublier de poser le `for` correspondant.

> Un texte visuellement proche d'un champ n'est un label que si le code le déclare explicitement : la proximité à l'écran ne vaut jamais association programmatique.

## En résumé

L'erreur axe « Form elements must have labels » ne ment jamais, même lorsqu'un label est visible à l'écran : elle signale l'absence d'une relation technique explicite entre le texte et le champ. Un `<label for>` correctement associé, ou à défaut un `aria-label`, corrige systématiquement ce problème, à condition de vérifier la correspondance exacte des identifiants sur chaque champ généré dynamiquement.
