Le champ de mot de passe
Un champ dont on ne peut ni relire ce qu'on a tapé, ni coller ce qu'un gestionnaire a généré. Trois attributs et un bouton suffisent à lever les deux obstacles. Démo, code, critères RGAA.
6 critères RGAA en jeu
Essayez-le
Ce que portent les éléments
- Type du champ
- Finalité déclarée
- Nom accessible du bouton
- Caractères dans le champ
- 0
Collez une longue phrase depuis votre gestionnaire de mots de passe : le compteur la reçoit entière. Rien n'intercepte le collage, rien ne tronque.
Tabulez jusqu’au bouton et pressez Entrée : son intitulé passe de
« Afficher » à « Masquer », et le relevé du bas montre le type du champ qui
suit. Puis collez une phrase longue depuis votre gestionnaire de mots de passe —
le compteur la reçoit entière, rien n’est intercepté ni tronqué.
Cette démo existe aussi en page autonome.
L’erreur courante
Deux fautes voyagent presque toujours ensemble : l’œil sans nom, et le collage interdit.
<!-- À ne pas faire -->
<input type="password" name="mdp" onpaste="return false" maxlength="16" />
<i class="icone-oeil" onclick="basculer()"></i> Le <i> ne prend pas le focus, ne répond ni à Entrée ni à
onpaste="return false" casse les gestionnaires de mots de passe. Celui qui
copie-colle un secret de trente signes le fait parce qu’il ne peut pas le taper
— ou pas sans erreur. L’interdiction ne laisse qu’une issue : un mot de passe
court, réutilisé, retenu de tête. Le RGAA 4.1, aligné sur WCAG 2.1, ne porte
aucun critère là-dessus ; WCAG 2.2 en a ajouté un depuis (3.3.8). Ce n’est donc
pas une non-conformité chez nous, et c’est quand même un obstacle réel.
maxlength="16", enfin, tronque en silence : le gestionnaire colle vingt-quatre
signes, le champ en garde seize, le compte est créé avec un mot de passe que
personne ne possède plus.
Trois variantes, aussi répandues :
autocomplete="off"posé sur tout le formulaire « pour la sécurité » : il prive le champ de sa finalité, et c’est exactement ce que le critère 11.13 relève.- Les règles de composition affichées seulement dans le message d’erreur : on saisit, on valide, on apprend, on recommence.
- Une bascule qui change l’icône mais garde le même nom accessible : l’état est visible et reste inaudible.
Le code, pas à pas
1. Le champ, son étiquette, sa finalité
<label for="mdp">Mot de passe</label>
<input id="mdp" type="password" autocomplete="current-password" /> type="password" masque la saisie et fait annoncer un champ protégé. La <label for> est la même exigence que partout — mais elle pèse plus ici,
puisque le contenu du champ ne peut pas servir de rappel.
Le choix entre les deux valeurs d’autocomplete n’est pas cosmétique :
current-passwordsur un formulaire de connexion — le gestionnaire propose le mot de passe enregistré pour ce compte ;new-passwordà la création et au changement — le gestionnaire propose d’en générer un, et se garde bien d’y remettre l’ancien.
Les deux figurent dans la liste normalisée des valeurs
d’autocomplete que le référentiel reprend de WCAG 2.1 : l’attribut n’accepte pas un mot libre.
2. Les règles, avant la saisie
<label for="mdp">Mot de passe</label>
<p id="mdp-regles">12 caractères au minimum.</p>
<input id="mdp" type="password" autocomplete="new-password" aria-describedby="mdp-regles" /> Le test 11.10.5 accepte deux conditions au choix, l’une comme l’autre préalables à la validation : une instruction visible qui identifie nommément le champ concerné, ou une instruction visible située dans l’étiquette ou dans le passage de texte associé au champ.
aria-describedby satisfait la seconde et fait restituer la règle en même temps
que l’étiquette, à l’arrivée dans le champ. Le test ne l’impose pas — il impose
la visibilité avant la validation.
Le message d’erreur, ensuite, reprend la règle mot pour mot plutôt que d’en donner une reformulation : lire « 12 caractères au minimum » au même endroit qu’avant évite de se demander si la contrainte a changé.
Une remarque qui n’est pas du RGAA mais qui allège la liste : le NIST, dans sa publication SP 800-63B, ne recommande plus les règles de composition — une majuscule, un chiffre, un symbole. Moins de règles, c’est moins à annoncer, moins à vérifier, et moins d’erreurs à rattraper.
3. La bascule afficher/masquer
<button type="button" id="bascule-mdp" aria-controls="mdp">
Afficher le mot de passe
</button> bascule.addEventListener('click', () => {
const masque = champ.type === 'password';
champ.type = masque ? 'text' : 'password';
bascule.textContent = masque ? 'Masquer le mot de passe' : 'Afficher le mot de passe';
statut.textContent = masque ? 'Votre mot de passe est visible.' : 'Votre mot de passe est masqué.';
}); Un <button type="button"> : sans le type, il soumettrait le formulaire — et
la moitié des bascules cassées le sont pour cette seule raison.
L’état se dit de deux façons, et il faut en choisir une.
- Le nom change : « Afficher le mot de passe » devient « Masquer le mot de passe ». C’est la solution la plus simple, et la plus sûrement restituée.
aria-pressed: le nom reste « Afficher le mot de passe », et l’état bascule. Le lecteur d’écran annonce alors « bouton bascule, activé ».
Les cumuler donne « Masquer le mot de passe, bouton bascule, activé », qui dit deux fois la même chose en se contredisant à moitié.
Le message de statut n’est pas un luxe : quand l’intitulé d’un bouton change
alors qu’il a le focus, le changement n’est pas réannoncé par tous les lecteurs
d’écran. Une région role="status", présente dès le premier rendu et vide, le
redit sans voler le focus.
Si la place manque et que le bouton n’affiche que « Afficher », le nom accessible doit contenir l’intitulé visible — c’est le test 11.9.2. Un complément masqué suffit, et c’est ce que fait la démo :
<button type="button">Afficher<span class="sr-only"> le mot de passe</span></button> 4. Ne rien intercepter
<input id="mdp" type="password" autocomplete="current-password" /> Il n’y a rien à écrire : le bon comportement est celui du navigateur. Ce qui se retire, en revanche :
- tout écouteur de
paste,copyoucontextmenusur le champ ; maxlength, sauf à une valeur qu’aucun gestionnaire n’atteindra ;- un
patternqui refuse l’espace ou les accents — il exclut les phrases de passe, précisément ce qu’on veut encourager ; autocomplete="off"sur le champ comme sur le formulaire.
Un masquage maison — un type="text" dont on remplace les caractères par des
points en JavaScript — cumule tous les défauts : le gestionnaire ne reconnaît
plus le champ, et le lecteur d’écran lit la vraie valeur à voix haute.
5. Un seul champ, plutôt que deux
« Confirmez votre mot de passe » existe parce qu’on ne pouvait pas relire ce qu’on venait de taper. La bascule répond mieux au même besoin, et pour la moitié du travail : un champ de moins à remplir, à annoncer, à valider — et un champ de moins où interdire le collage par distraction.
Au clavier
| Touche | Effet |
|---|---|
| Tab | Va au champ, puis au bouton afficher/masquer, placé juste après lui dans le code. |
| Ctrl+V / Cmd+V | Colle le mot de passe. Rien ne doit l’intercepter. |
| Entrée / Espace | Sur le bouton : bascule l’affichage. Le focus reste sur le bouton, la valeur reste dans le champ. |
| Entrée | Dans le champ : soumet le formulaire. |
Ce que le lecteur d’écran restitue
À l’arrivée dans le champ, le nom, la nature protégée et la règle liée — de l’ordre de « Mot de passe, saisie de texte sécurisée, 12 caractères au minimum ». La formulation varie d’un lecteur d’écran à l’autre, les informations non.
Pendant la frappe, en revanche, rien n’est épelé : un champ masqué fait dire « étoile », ou ne fait rien dire. C’est la raison d’être de la bascule, et ce qui rend son inaccessibilité si coûteuse.
Sur le bouton : « Afficher le mot de passe, bouton ». Après activation, le statut suit — « Votre mot de passe est visible » — et le bouton se nomme désormais « Masquer le mot de passe ».
Si vous n’entendez que « bouton », l’icône n’a pas de nom accessible. Si le nom ne change pas et qu’aucun « activé » ne suit, l’état n’est pas exposé. Et si vous n’entendez la règle des douze caractères qu’après avoir validé, c’est qu’elle n’est reliée à rien.
Checklist
type="password"et une<label for>visible — jamais un placeholder seul.autocomplete="current-password"à la connexion,new-passwordà la création.- Les règles de saisie visibles avant la validation —
aria-describedbyles rattache au champ. - La bascule en
<button type="button">, jamais une icône cliquable. - L’état porté par un nom qui change ou par
aria-pressed— pas les deux. - Une région
role="status"pour redire le changement, présente dès le départ. - Rien qui intercepte le collage, aucun
maxlengthqui tronque.
Les critères RGAA en jeu
- Critère 11.13 — Remplissage automatique des champs
C'est le seul champ qu'on ne saisit presque jamais de tête. Sans autocomplete current-password ou new-password, le gestionnaire ne reconnaît plus le champ, et l'utilisateur retombe sur ce qu'il retient.
- Critère 11.10 — Contrôle de saisie
Les contraintes du mot de passe — longueur, caractères acceptés — doivent être visibles avant la validation : dans l'étiquette, dans le texte associé au champ, ou dans une instruction qui nomme le champ. Les découvrir dans le message d'erreur, c'est les découvrir trop tard.
- Critère 11.9 — Intitulé des boutons
La bascule afficher/masquer est un bouton du formulaire : une icône en forme d'œil sans intitulé ne dit ni ce qu'elle fait, ni sur quoi elle agit.
- Critère 7.1 — Compatibilité des scripts
La bascule est scriptée, donc son changement d'état doit être exposé — par un nom qui change ou par aria-pressed. Un œil qui se barre ne parle qu'à l'œil.
- Critère 7.3 — Contrôle des scripts au clavier
Une icône qui écoute le clic sans être un bouton ne prend pas le focus : relire ce qu'on vient de taper devient impossible sans souris, dans le seul champ où le navigateur ne le montre pas.
- Critère 11.1 — Étiquette de champ de formulaire
Le champ est masqué et sa valeur illisible : quand l'étiquette n'est qu'un placeholder, elle disparaît à la première frappe et plus rien, pas même la saisie, ne rappelle de quel champ il s'agit.
Vérifiez votre composant avec l'extension
Pour aller plus loin
- Critère 11.13 — Remplissage automatique des champs et 11.10 — Contrôle de saisie : les deux critères que ce champ met le plus souvent en défaut.
- Critère 11.9 — Intitulé des boutons : ce qu’un audit attend du bouton afficher/masquer, test par test.
- Les champs de formulaire : l’étiquette, l’aide et l’erreur, valables pour tous les champs.
- « Liste des valeurs possibles pour l’attribut
autocomplete» au glossaire : les jetons que le référentiel accepte.
Sources
- ARIA APG — Button Pattern — le bouton bascule et
aria-pressed - MDN —
<input type="password">— la référence du champ - WCAG — Understanding 1.3.5 Identify Input Purpose — pourquoi la finalité du champ se déclare
- GOV.UK Design System — Password input — une bascule éprouvée à grande échelle