Formulaires HTML

Alexandre Niveau
GREYC — Université de Caen
Avant de commencer, retourner montrer le cours sur les URL pour reparler des paramètres. Créer un fichier HTML, montrer qu'on peut mettre des paramètres dans l'URL, mais que ça ne fait rien. C'est en fait utile pour les pages dynamiques, dont le HTML est généré par un programme et non écrit à la main. Le programme accède aux paramètres et peut adapter le HTML généré. Montrer l'exemple de la page de cours : fonctionnement du mode proj, et paramètre punchy.

Formulaires HTML

Le langage HTML fournit une interface permettant aux internautes de communiquer des informations au serveur web : les formulaires

Ils sont principalement utiles pour envoyer des données (par la méthode POST du protocole HTTP) : poster un commentaire, s'authentifier sur un site…

Mais ils permettent aussi de spécifier des paramètres pour une page : champ de recherche, contrôle de l'affichage du contenu (ordre, filtrage)…

Ils fonctionnent exactement de la même manière pour les deux usages : des widgets (éléments d'interface) permettent à l'internaute de choisir des valeurs pour des « variables » spécifiées dans le code

Base d'un formulaire

L'élément représentant un formulaire est form

On peut mettre des éléments classiques à l'intérieur (comme du texte, des paragraphes, des div…), mais surtout des widgets

La plupart des widgets sont créés avec l'élément input, qui donne des résultats très différents en fonction de son attribut type :
<form>
   <input type="text" />
   <input type="checkbox" />
   <input type="radio" />
</form>

Labels

Les légendes des champs du formulaires doivent être placés dans des éléments label (étiquettes)

Les labels doivent être explicitement associés à leurs champs : extrêmement important pour l'accessibilité et pour l'ergonomie !

Pour associer un label à un champ, le plus simple est de mettre le champ dans le label :
<form>
  <label>Ville : <input type="text" /></label>
  <label>Capitale : <input type="checkbox" /></label>
</form>
(Cliquer sur les labels !)

Si on ne veut ou ne peut pas mettre le champ dans le label, on peut également donner un id au champ et relier le label à ce champ en spécifiant son identifiant dans l'attribut for du label.

Bouton de soumission

Un formulaire est inutile si on ne peut pas le soumettre

Élément button
<form>
   <input type="text" value="Texte par défaut" />
   <button type="submit">Envoyer !</button>
</form>
Trois types de bouton :
  • submit envoie les données
  • reset remet tous les champs du formulaire à leur valeur par défaut
  • button ne fait rien ! Utile pour les scripts côté client

Noms des paramètres

Les données entrées sur les widgets servent à donner des valeurs à des variables

Il faut donner des noms à ces variables, pour que le serveur sache à quoi sert chaque donnée !

La plupart des widgets utilisent l'attribut name pour cela
<form>
   <input type="text" value="Caen" name="ville" />
   <input type="text" value="France" name="pays" />
   <input type="checkbox" name="coche" />
   <button type="submit">Envoyer !</button>
</form>

Attention au comportement des checkbox

Ne pas confondre les attributs name et id

Utilisation des données comme paramètres d'une page

Dans l'exemple précédent, cliquer sur le bouton recharge la même page, mais l'URL a changé car le navigateur a ajouté des paramètres d'URL, construits à partir des noms des widgets et des valeurs fournies par l'internaute

Pour renvoyer vers une autre page, il faut donner l'URL dans l'attribut action de l'élément form

Dans cet exemple on renvoie vers une page qui fait quelque chose avec les paramètres :

<form action="demo/recup.php">
   <input type="text" value="Caen" name="ville" />
   <input type="text" value="France" name="pays" />
   <input type="checkbox" name="coche" />
   <button type="submit">Envoyer !</button>
</form>

NB : une simple page HTML ne sait rien faire avec les paramètres d'URL, c'est le serveur qui va analyser les paramètres et modifier le HTML envoyé en fonction. La récupération et l'utilisation des données envoyées sortent largement du cadre du cours de HTML.

Envoi des données

Les paramètres d'URL ne conviennent pas à toutes les situations

On a souvent besoin d'envoyer des données au serveur

Dans ce cas, on peut spécifier que le navigateur doit utiliser la méthode POST de HTTP, en écrivant method="POST" comme attribut de l'élément form (la valeur par défaut de method est GET ⇒ construit une URL paramétrée)

<form action="demo/recup.php" method="POST">
   <input type="text" value="Caen" name="ville" />
   <input type="text" value="France" name="pays" />
   <input type="checkbox" name="coche" />
   <button type="submit">Envoyer !</button>
</form>

Encore une fois, la récupération des données côté serveur sort largement du cadre du cours. Cependant il est bon de comprendre dès maintenant la différence d'utilisation entre les deux méthodes.

Si hésitation entre paramètres d'URL et méthode POST, se demander si l'URL paramétrée aurait un sens en tant que lien. Il n'est envisageable d'utiliser la méthode GET que si la réponse est oui.

Attention : les données de la requête POST ne sont pas affichées par les navigateurs, mais elles ne sont pas cachées !
  • Il est possible de les voir (par ex. avec l'outil « network monitor » de Firefox)
  • Elles circulent en clair sur le réseau

Ne pas penser que POST est plus sécurisé que GET

Boutons radio

Les boutons radio n'ont d'intérêt qu'en groupe : un seul peut être sélectionné

C'est l'attribut name qui les groupe

Le paramètre prendra la valeur du bouton sélectionné : cette valeur correspond à l'attribut value
<form action="demo/recup.php" method="POST">
  Les formulaires HTML, vous êtes :
  <label><input type="radio" value="oui" name="fan" /> Fan</label>
  <label><input type="radio" value="non" name="fan" /> Pas fan</label>
  <label><input type="radio" value="?" name="fan" /> NSPP</label>
  <button type=submit>Envoyer !</button>
</form>
Les formulaires HTML, vous êtes :

Grouper des champs

L'élément fieldset permet de grouper des champs qui ont un rapport logique entre eux et de leur associer un label commun avec legend

Utile notamment pour les cases à cocher et les boutons radio
<form action="demo/recup.php" method="POST">
    <fieldset>
      <legend>Les formulaires HTML, vous êtes :</legend>
      <label><input type="radio" value="oui" name="fan" /> Fan</label>
      <label><input type="radio" value="non" name="fan" /> Pas fan</label>
      <label><input type="radio" value="?" name="fan" /> NSPP</label>
    </fieldset>
    <button type=submit>Envoyer !</button>
</form>
Les formulaires HTML, vous êtes :

Texte multi-lignes

On utilise l'élément textarea pour du texte sur plusieurs lignes
<form action="demo/recup.php" method="POST">
  <textarea cols="30" rows="5" name="multi">Mettre du texte ici !</textarea>
  <button type="submit">Go</button>
</form>

Propriété CSS resize pour que l'internaute puisse modifier la taille (valeurs : horizontal, vertical, both)

Attention, contrairement à input, textarea a une balise ouvrante et une balise fermante (le contenu est utilisé comme valeur par défaut)

Valeur par défaut et placeholder

Dans les champs texte, on peut mettre une valeur par défaut :
<form action="demo/recup.php" method="POST">
  <input type="text" size="10" name="prenom" value="Prénom" />
  <textarea cols="10" rows="5" name="comm">Votre commentaire…</textarea>
  <button type="submit">Envoyer</button>
</form>

L'internaute doit effacer le contenu avant de taper

En règle générale, c'est plutôt une sorte de « mode d'emploi » qu'on voudrait

Il faut utiliser l'attribut placeholder :
<form action="demo/recup.php" method="POST">
  <input type="text" size="10" name="prenom" placeholder="Prénom" />
  <textarea cols="10" rows="5" name="comm" placeholder="Votre commentaire…"></textarea>
  <button type="submit">Envoyer</button>
</form>

Attention, les exemples ci-dessous sont simplifiés : dans la pratique, il ne faut jamais utiliser un placeholder à la place d'un label ! Le formulaire doit être compréhensible sans le placeholder, qui n'est pas toujours affiché.

Menu déroulant

Le menu déroulant s'obtient avec l'élément select, qui contient plusieurs éléments option
<form action="demo/recup.php" method="GET">
  <select name="fruit">
    <option>Fraise</option>
    <option>Pomme</option>
    <option>Raisin</option>
  </select>
  <button type="submit">Go</button>
</form>

La valeur du paramètre est le contenu de l'élément option sélectionné, ou le contenu de son attribut value s'il existe

Groupes d'options dans un menu

On peut grouper les options d'un menu déroulant avec l'élément optgroup
<form action="demo/recup.php" method="GET">
  <select name="instrument">
    <optgroup label="Bois">
      <option value="clarinette">Clarinette (si♭)</option>
      <option value="basson">Basson (ut)</option>
      <option value="sax">Saxophone (mi♭)</option>
    </optgroup>
    <optgroup label="Cuivres">
      <option value="trompette">Trompette (si♭)</option>
      <option value="trombone">Trombone (ut)</option>
      <option value="tuba">Tuba (fa)</option>
    </optgroup>
  </select>
  <button type="submit">Go</button>
</form>

remarquer l'utilisation de value (on n'utilise pas les noms « compliqués » des instruments dans le code)

Améliore aussi l'accessibilité

Menu à choix multiples

Choix multiples possibles en utilisant un menu déroulant select avec l'attribut booléen multiple
<form action="demo/recup.php" method="GET">
  <select multiple name="fruit">
    <option>Fraise</option> <option>Pomme</option>
  </select>
  <button type="submit">Go</button>
</form>

NB : attribut booléen = pas besoin de valeur, la simple présence de l'attribut lui donne la valeur « vrai »

Si on teste l'exemple précédent, on voit que le paramètre est défini plusieurs fois dans l'URL. Il faut que le script de récupération sache quoi faire. Avec PHP, le plus simple est d'utiliser une syntaxe particulière pour le nom :
<form action="demo/recup.php" method="GET">
  <select multiple name="fruit[]">
    <option>Fraise</option> <option>Pomme</option>
  </select>
  <button type="submit">Go</button>
</form>

Autres widgets

Il existe un certain nombre de input différents, notamment des variantes du champ text qui donnent plus de sémantique : email, url, number

Intérêt : éviter les erreurs de l'internaute (on ne peut pas soumettre le formulaire si les valeurs sont incohérentes) et augmenter l'ergonomie (par exemple les claviers proposés sur mobile peuvent être adaptés au champ)

Voir par exemple ce guide en français sur Alsacréations

Quelques compléments

Attribut target de l'élément form : indique où sera affichée la réponse. _self pour la même fenêtre (ou iframe), _blank pour une nouvelle

Attribut booléen checked : permet qu'une case soit cochée par défaut, ou qu'un bouton radio soit sélectionné par défaut.

Attribut booléen selected : idem, mais pour une option dans un menu déroulant.

Validation côté client

Attribut booléen disabled : valable pour tous les widgets, permet de les rendre non modifiables.

Attribut booléen required : valable pour tous les widgets, permet de les rendre obligatoires.

Voir le tutoriel sur MDN pour d'autres compléments sur la validation des formulaires (attributs HTML pattern, minlength et maxlength, min et max, etc., pour empêcher l'internaute de soumettre des valeurs aberrantes)

Style des formulaires

Tout n'est pas modifiable par CSS dans les formulaires, notamment les menus déroulants…

Pour sélectionner un type d'input : utiliser les sélecteurs par attribut
input[type=text] {
	border: 2px dotted green;
}
Nombreuses pseudo-classes utiles pour les éléments de formulaire
  • :focus, sélectionne les éléments qui ont le focus, très utile pour les champs texte
  • :checked sélectionne les cases cochées, les boutons radio sélectionnés, et les options choisies dans un menu déroulant (peut être détourné, un peu comme :target, pour rendre les pages un peu dynamiques !)
  • :default sélectionne les éléments qui sont dans leur état par défaut (ex.: cases à cocher)
  • :valid et :invalid, pour styler les champs dont la validation est correcte ou non
  • :disabled et :enabled sélectionnent les éléments désactivés ou non par l'attribut HTML disabled
  • :required et :optional sélectionnent les élements obligatoires ou non (attribut HTML required)

Attention à width : les widgets ont chacun leur propre interprétation. Préciser box-sizing: border-box; pour être tranquille

Tous les détails sur le tutoriel de MDN