CSS : Les formulaires
Introduction Introduction
La plupart du temps, lorsque que l’on souhaite gérer la validation du formulaire, on a recours au javascript pour gérer l’affichage des erreurs et avec éventuellement un style d’erreur sur les champs via des classes spécifiques. Avec les récentes nouveautés CSS et HTML, il est possible de déléguer une certaine partie de ces erreurs au CSS.
Règles avec HTML Règles avec HTML
Rendre un champ obligatoire Rendre un champ obligatoire
Il suffit de mettre un attribut required
pour que le navigateur sache que le formulaire ne doit pas être envoyé si le champ est vide.
Il applique alors un état invalide au champ ainsi qu’au formulaire.
<input id="input" required="required" name="name" />
Les types de champs Les types de champs
Comme pour les champs obligatoires, les types permettent également d’effectuer des vérifications de format (Ex: email, tel, …). On peut même appliquer des patterns avec des expressions régulières.
<label for="input">Input</label>
<input
id="input"
required="required"
name="name"
aria-describedby="input-message"
pattern="^[^\d]*$"
/>
Personnaliser les messages
Nativement, les navigateurs affichent un message d’erreur dans une info-bulle lors de la soumission du formulaire, il est possible de compléter le message par exemple pour préciser le format attendu.
Pour cela, il faut utiliser l’attribut title
:
<input
type="text"
pattern="[0-9]{3}-[0-9]{3}-[0-9]{4}"
name="phone_number"
required
title="Le format attendu est 555-555-5555"
/>
Soumission du formulaire Soumission du formulaire
La soumission du formulaire sera automatiquement bloquée si un des champs n’est pas valide. Il n’est pas nécessaire de stopper son comportement via un écouteur d’évènement et un e.preventDefault()
.
Validation avec CSS Validation avec CSS
Maintenant que l’on a vu comment fixer les règles sur nos champs, voyons comment exploiter ces erreurs avec le CSS.
Gérer l'affichage avec les attributs
Plutôt que d’ajouter des classes en fonction des différents états de votre champ, je conseille plutôt de se baser sur les attributs HTML. Par exemple, pour un champ désactivé, il est préférable de le cibler via l’attribut :
input:is([disabled], [aria-disabled='true']) {
cursor: not-allowed;
}
Champ obligatoire Champ obligatoire
La pseudo-classe qui permet d’identifier si un champ est obligatoire est :required
, Par exemple, on peut ajouter une étoile à côté du label si le champ est obligatoire.
Pour cela, on peut le combiner avec le :has()
label:has(+ input:required):after {
content: ' *';
}
Champ valide Champ valide
La pseudo-classe qui permet d’identifier si un champ est valide est :user-valid
, il suffit de lui appliquer un style de validation.
Il existe une autre pseudo-classe :valid
, la différence entre les deux et que :user-valid
ne réagit qu’après une interaction utilisateur.
input:user-valid {
border: 2px solid green;
}
input:user-valid + span::before {
content: '✓';
color: green;
}
Champ invalide Champ invalide
La pseudo-classe qui permet d’identifier si un champ est invalide est :user-invalid
, il suffit de lui appliquer un style d’erreur.
Il existe une autre pseudo-classe :invalid
, la différence entre les deux et que :user-invalid
ne réagit qu’après une interaction utilisateur.
input:user-invalid {
border: 2px solid red;
}
input:user-invalid + span::before {
content: '❌';
color: red;
}
Gestion du focus Gestion du focus
La gestion de la tabulation est très importante lorsque l’on développe un formulaire notamment pour garantir une bonne accessibilité.
Gestion du focus Gestion du focus
Lorsque l’on navigue avec la tabulation, il est primordial que l’utilisateur sache où il se trouve dans la page, sur quel élément il est positionné.
Pour l’ensemble des éléments focusables, la gestion du focus est gérée par les navigateurs avec une propriété de style outline
que l’on pourra personnaliser.
La pire erreur en termes d’accessibilité serait de la supprimer.
:focus() :focus()
Pour appliquer cette modification, nous pouvons utiliser la pseudo-class :focus
. On peut alors modifier le outline
comme ceci :
input:focus {
outline: 1px solid blue;
outline-offset: 2px;
}
:focus-visible() :focus-visible()
Le problème avec :focus
, c’est qu’il se déclenche également sur évènement ‘click’, par exemple si on applique ce style :
button:focus {
outline: 1px solid blue;
outline-offset: 2px;
}
Cela n’a pas grand intérêt d’indiquer le focus d’un bouton lorsque l’utilisateur clique dessus. Si on souhaite uniquement afficher le outline
pour la tabulation, on peut plutôt utiliser le :focus-visible
.
Voir la doc MDN de :focus-visible
:focus-within() :focus-within()
Si on souhaite détecter si un des champs est en état “focus” depuis un élément parent, nous pourrions utiliser le :has()
:
fieldset:has(input:focus) {
}
On peut faire la même chose avec la pseudo-classe :focus-within
, elle est utile, lorsque l’on souhaite mettre en avant une sous-partie de formulaire et que l’utilisateur est “focus” sur un des champs.
fieldset:focus-within {
}
Voir la doc MDN de :focus-within
Exemple de formulaire Exemple de formulaire
Si vous chercher un exemple d’utilisation de ces pseudo-class, le formulaire de contact de ce site les utilise.
Si souhaitez jouer avec, voici un codepen