frontend / html
Formulaires avancés : types d'inputs et validation native
Explication
Ce que vous allez apprendre
- Choisir le bon type d'
<input>(email,date,tel,range...) pour chaque besoin de saisie - Utiliser
required,min,max,patternetminlengthpour valider sans JavaScript - Comprendre pourquoi la validation native n'est jamais suffisante seule côté sécurité
- Personnaliser un message d'erreur natif avec
setCustomValidity() - Ajouter de l'autocomplétion légère avec
<datalist>
Dans quel contexte ?
Un développeur backend refuse une pull request sur formulaire-inscription.html : le champ téléphone accepte n'importe quelle chaîne de caractères côté client, ce qui envoie des données mal formées à l'API. En ajoutant type="tel" pattern="[0-9]{10}", le navigateur bloque déjà la soumission si le format est incorrect et affiche un message natif, avant même que la requête ne parte vers le serveur. C'est un gain d'UX immédiat, mais qui ne dispense jamais de revalider ce même champ côté API.
Étape 1 : le réflexe à corriger chez le débutant
Beaucoup de développeurs juniors pensent que toute validation de formulaire doit passer par du JavaScript personnalisé. C'est une idée fausse : le navigateur embarque déjà un système de validation complet et gratuit, testé sur des milliards d'appareils.
Étape 2 : un simple changement de type fait déjà beaucoup
Prenons le cas le plus simple. Choisir type="email" plutôt que type="text" n'est pas juste cosmétique : le navigateur adapte automatiquement le clavier virtuel sur mobile, avec le symbole @ accessible directement.
Étape 3 : et ça va plus loin que le clavier
En plus du clavier adapté, chaque type spécialisé affiche une interface dédiée — un sélecteur pour type="date", un curseur pour type="range" — ET valide le format tout seul, sans une seule ligne de JavaScript. Un type d'input, c'est donc trois avantages en un : ergonomie, cohérence visuelle, et validation.
Étape 4 : ajouter des règles précises avec des attributs
Une fois le bon type choisi, on peut affiner avec des attributs comme required, min, max, pattern ou minlength. Le navigateur vérifie automatiquement ces règles au moment de soumettre le formulaire.
Étape 5 : que se passe-t-il si une règle est violée
S'il détecte un problème, le navigateur empêche l'envoi et affiche un message d'erreur natif, positionné directement sous le champ concerné — toujours sans JavaScript. Pour aller plus loin, une API (element.validity) permet même de personnaliser ces messages.
| Type d'input | Clavier mobile adapté | Validation native intégrée |
|---|---|---|
email | Clavier avec @ | Format email basique |
tel | Clavier numérique | Aucune (utiliser pattern) |
url | Clavier avec / et .com | Format URL |
number | Clavier numérique | min/max/step |
date | Sélecteur de date natif | Format date valide |
Prérequis
Cette leçon suppose que vous maîtrisez déjà les bases des formulaires (<label>, <input>, name) vues à la leçon précédente.
Le piège à connaître avant de continuer
Il reste un point crucial à ne jamais oublier : cette validation native protège l'expérience utilisateur côté navigateur, mais elle ne remplace JAMAIS une validation côté serveur. N'importe qui peut désactiver JavaScript ou envoyer une requête directement à l'API sans passer par le formulaire.
Retenez cette règle simple : la validation HTML améliore l'UX, la validation serveur garantit la sécurité — les deux sont nécessaires, jamais l'une à la place de l'autre.
Piège fréquent
Ne jamais faire confiance uniquement à required ou pattern pour sécuriser une API. N'importe qui peut envoyer une requête POST directement avec curl ou Postman, en contournant totalement le formulaire et sa validation native.
Et ensuite ?
Une fois les formulaires maîtrisés, la prochaine étape consiste à sortir de la "div-ite" en apprenant la sémantique avancée : article, section, nav, aside.
Commandes & code
Formulaires avancés : types d'inputs et validation native
Le navigateur peut valider énormément de choses sans une ligne de JavaScript.
<!-- Types d'input spécialisés : chacun adapte le clavier mobile et l'UI -->
<input type="date" name="naissance">
<input type="time" name="heure">
<input type="datetime-local" name="rdv">
<input type="week" name="semaine">
<input type="month" name="mois">
<input type="tel" name="telephone" pattern="[0-9]{10}" placeholder="0600000000">
<input type="url" name="site" placeholder="https://exemple.com">
<input type="search" name="q" placeholder="Rechercher...">
<input type="color" name="couleur" value="#3366ff">
<input type="range" name="volume" min="0" max="100" step="5" value="50">
<input type="file" name="avatar" accept="image/png, image/jpeg" multiple><!-- Validation native complète, sans JS -->
<form novalidate id="formInscription">
<label for="pseudo">Pseudo (3-15 caractères)</label>
<input
type="text"
id="pseudo"
name="pseudo"
required
minlength="3"
maxlength="15"
pattern="[a-zA-Z0-9_]+"
title="Lettres, chiffres et underscore uniquement"
>
<label for="email">Email professionnel</label>
<input
type="email"
id="email"
name="email"
required
pattern=".+@entreprise\.com$"
>
<label for="quantite">Quantité (1 à 10)</label>
<input type="number" id="quantite" name="quantite" min="1" max="10" step="1" required>
<button type="submit">Valider</button>
</form>
<script>
// L'API de validation native reste accessible en JS pour des messages custom
const email = document.getElementById("email");
email.addEventListener("invalid", () => {
if (email.validity.patternMismatch) {
email.setCustomValidity("Utilisez votre adresse @entreprise.com");
} else {
email.setCustomValidity(""); // reset sinon le message reste bloqué
}
});
email.addEventListener("input", () => email.setCustomValidity(""));
</script><!-- datalist : autocomplétion native, sans framework -->
<label for="langage">Langage préféré</label>
<input list="langages" id="langage" name="langage">
<datalist id="langages">
<option value="JavaScript">
<option value="Python">
<option value="Rust">
<option value="Go">
</datalist>
<!-- Attributs de validation transversaux -->
<input type="text" required aria-describedby="aide-pseudo">
<span id="aide-pseudo">3 caractères minimum</span>Propriété JS (element.validity) | Sens |
|---|---|
valueMissing | champ requis vide |
patternMismatch | ne respecte pas pattern |
rangeOverflow/rangeUnderflow | hors de min/max |
tooShort/tooLong | hors de minlength/maxlength |
Résumé
- Les types d'input spécialisés adaptent automatiquement clavier et UI mobile.
pattern,min,max,minlength,maxlengthcouvrent 80% des besoins de validation.setCustomValidity()personnalise les messages sans réinventer la validation.datalistfournit une autocomplétion native légère.
Exercices pratiques
Mission : faire accepter la pull request du champ téléphone
Objectif : Corriger un champ téléphone qui accepte n'importe quelle chaîne, tout en comprenant pourquoi cette correction ne suffit pas côté sécurité.
Contexte
Un développeur backend refuse une pull request sur formulaire-inscription.html : le champ téléphone est un simple <input type="text" name="telephone">, qui accepte n'importe quelle chaîne de caractères et envoie des données mal formées à l'API.
Ta mission : corriger ce champ côté client, puis expliquer les limites de cette correction.