« Ce champ est obligatoire. » Le message apparaît bien à l’écran sous le champ Téléphone d’un formulaire de contact, en rouge, avec une icône d’alerte. Mais rien ne se passe côté lecteur d’écran : aucune annonce vocale, aucun déplacement de focus, comme si le message n’existait pas pour qui ne le voit pas.
Ce cas a été remonté sur un site vitrine construit à partir de l’éditeur de blocs, où le formulaire de contact avait été créé une première fois, puis dupliqué sur trois autres pages avec de légères variations (un champ « Sujet » en plus ici, un champ « Société » en moins là). Ce mode de duplication, très répandu dès qu’un motif de bloc doit être adapté à plusieurs contextes, est précisément ce qui a fait perdre l’attribut en cours de route.
Symptôme : un message visible mais silencieux
Au clavier, tout semblait fonctionner : la tabulation atteignait bien le champ Téléphone, la validation du formulaire échouait bien, le message rouge s’affichait bien sous le champ. Mais avec NVDA activé, rien ne se produisait à la soumission : aucune annonce d’erreur, aucun déplacement du focus vers le champ fautif. L’utilisateur de lecteur d’écran validait le formulaire, entendait un silence, et n’avait aucune raison de comprendre pourquoi la page ne changeait pas d’état.
Diagnostic : comparer les quatre versions du motif
La première piste, souvent la bonne dans ce genre de cas, consiste à comparer le HTML généré sur les quatre pages concernées plutôt que de supposer que le motif est identique partout. L’inspection a montré ceci :
<!-- Page 1, motif d'origine -->
<input type="tel" id="telephone" name="telephone" required
aria-describedby="erreur-telephone">
<!-- Page 3, motif dupliqué puis modifié -->
<input type="tel" id="telephone" name="telephone">
Sur la page 3, quelqu’un avait retiré temporairement l’attribut required pour tester un comportement de validation côté serveur, sans jamais le remettre. Le message d’erreur visuel, lui, restait affiché par un script JavaScript générique qui vérifiait la présence d’une valeur non vide indépendamment de l’attribut HTML, ce qui explique pourquoi le message apparaissait à l’écran sans jamais être relié au champ ni annoncé.

Correctif : rétablir l’attribut et lier le message
Le correctif tient en deux parties distinctes, souvent confondues à tort en une seule :
- Rétablir l’attribut
requiredsur le champ, ce qui restaure la validation native du navigateur et son message d’erreur accessible par défaut. - S’assurer que le message d’erreur personnalisé, affiché en plus du message natif pour des raisons de cohérence visuelle avec la charte du site, reste bien associé au champ via
aria-describedbyet devient visible pour les technologies d’assistance au moment de son apparition.
<input type="tel" id="telephone" name="telephone" required
aria-describedby="erreur-telephone" aria-invalid="true">
<span id="erreur-telephone" role="alert">
Le numéro de téléphone est obligatoire.
</span>
L’ajout de aria-invalid="true" au moment de l’échec de validation, retiré dès que le champ redevient valide, donne un signal supplémentaire cohérent avec le message affiché.
Prévention : sortir de la copie manuelle de motif
Le vrai problème de fond n’est pas l’oubli d’un attribut, c’est le mode de duplication qui l’a permis. Copier un motif de formulaire quatre fois puis le modifier séparément revient à créer quatre sources de vérité indépendantes, condamnées à diverger tôt ou tard. Deux options réduisent ce risque :
- Construire un motif synchronisé unique dans l’éditeur de blocs, avec des surcharges limitées aux champs réellement variables (le champ Sujet en plus, par exemple), plutôt que de dupliquer l’ensemble de la structure.
- À défaut, documenter clairement dans le motif d’origine la liste des attributs qui ne doivent jamais être retirés, avec un commentaire visible pour quiconque modifie une copie.
Conseil maison : un test de validation qui vérifie uniquement l’affichage visuel du message d’erreur ne détecte jamais ce genre de régression. Testez toujours au clavier avec un lecteur d’écran actif.
En résumé
Ce genre de régression est particulièrement sournois parce qu’il ne casse rien de visible : le message d’erreur reste là, en rouge, parfaitement lisible à l’œil. C’est précisément ce qui le rend dangereux, puisqu’un contrôle visuel rapide ne le repère jamais. Seul un test avec une technologie d’assistance active révèle l’écart entre ce que voit une personne voyante et ce qu’entend une personne aveugle.