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"
/>

Error input on Edge

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

Retour à la liste des articles
Github de Samuel Gomez Linkedin de Samuel Gomez Twitter de Samuel Gomez Instagram de Samuel Gomez
Allez en haut