HTML permet, via des objets nommés "formulaire", d'interagir avec l'utilisateur au delà des simples liens de navigation. Il est possible de faire faire des choix à l'utilisateur ou de lui demander de remplir des informations. Une fois le formulaire rempli, il est envoyé par le navigateur et analysé par un programme sur le serveur Web. Parmi leurs utilisations courantes on peut noter :

- Récupérer des informations sur l'utilisateur (par exemple nom/prénom) ;

- Procéder à des authentifications ;

- Permettre à l'utilisateur de contribuer à un site (via des forums par exemple) ;

- Opérer des recherches ou sélections sur le site ;

- etc.

Les exemples décrits plus bas sont faits en XHTML 1.0.

### Définir un formulaire simple

#### Délimitation

Un formulaire est délimité par la balise `<form>` . La délimitation permet d'en mettre plusieurs indépendants sur une même page et d'en définir les paramètres généraux d'envoi. Si plusieurs formulaires peuvent exister sur une page, il est interdit de les imbriquer : une même zone ne peut être contenue que par un et un seul formulaire. La balise contient un attribut obligatoire nommé `action`, dont nous verrons plus loin l'utilité.

#### Emplacement dans la page et structure

La balise de formulaire n'est qu'un délimiteur, elle est destinée à recevoir des éléments de niveau bloc et non du contenu dit "en-ligne" (pour plus d'informations, voir l'article Boîtes bloc, boîtes en ligne et propriété display). Elle est donc elle même une balise de type bloc, et à ce titre ne peut pas être incluse dans un paragraphe (ou autre élément qui n'accepte que le contenu en-ligne).

Pour pouvoir y insérer des éléments comme des cases à cocher ou du texte (qui sont du contenu en-ligne), vous devrez les regrouper dans une balise comme `<p>` (paragraphe), `<li>` (élément de liste) ou `<div>` (balise de type bloc qui accepte le contenu en-ligne).

    <div>
      <form action="...">
        <p>texte</p>
      </form>
    </div>

#### Champs de données

Commençons d'abord par demander le nom du visiteur. Pour qu'il puisse l'inscrire nous allons créer un champ (balise `<input>` ) de type texte (attribut `type="text"`). À l'affichage le visiteur aura une zone de saisie simple où il pourra écrire du texte.

    <input type="text" value="exemple" />

Exemple de champ texte.

#### Description du champ

Afin que l'utilisateur puisse savoir à quoi sert ce champ de texte il est nécessaire de lui donner une légende ou un titre. Les descriptions de champs sont faites à l'aide de la balise `<label>` .

Cette balise est souvent oubliée mais est indispensable à la compréhension de votre formulaire pour de nombreuses personnes employant des méthodes de navigation alternatives. Sans elle, ces personnes seront dans l'impossibilité de comprendre le rôle de chaque champ du formulaire, et donc de le remplir.

Un champ correctement symbolisé facilitera d'ailleurs l'accès d'un formulaire à tout le monde puisque cliquer sur la légende activera le champ concerné. Pour un champ texte il s'agit d'y déplacer le focus clavier, pour une case à cocher cliquer sur la légende cochera la case. Ce sont ces petits plus qui améliorent l'ergonomie pour l'utilisateur final.

Pour indiquer une description de champ, on inclus celle-ci entre les balises de label et on indique, par l'attribut `"for"`, l'id du champs auquel la description est rattachée, comme ceci :

    <form action="...">
      <p>
        <label for="nom">Nom :</label>
        <input type="text" id="nom" />
      </p>
    </form>

Il existe une autre façon d'utiliser la balise `<label>` : celle d'inclure le champs de saisie entre les balises de label, en même temps que la description :

    <form action="...">
      <p>
        <label for="nom">
          Nom : <input type="text" id="nom" />
        </label>
      </p>
    </form>

Dans ce cas, en théorie, il est possible d'omettre l'attribut `"for"`, mais les navigateurs ne savent pas tous bien gérer cette situation, en particulier Internet Explorer (il ne fait pas la liaison entre le champs et sa description, et donc par exemple, un clic sur le label ne mettra pas le focus sur le champs de saisie). Il est donc recommandé de toujours mettre l'attribut `"for"`.

Exemple d'utilisation de `<label>` .

#### Désignation des champs

Le contenu du formulaire est normalement destiné à être envoyé à un programme sur le serveur Web. À la réception, le programme doit pouvoir connaître le contenu de chaque élément, donc identifier les différentes données. Cette identification est faite en attribuant un nom à chaque champ du formulaire, via l'attribut `"name"`. Cet attribut n'est pas unique. Vous pouvez par exemple avoir plusieurs formulaires dans une même page, certains ayant des champs nommés de la même façon. Le programme serveur qui interprète le formulaire n'aura alors pas à savoir sur quel formulaire l'utilisateur a cliqué, il interprétera les données uniquement à partir de leur nom.

Attention à ne pas confondre le nom (attribut `"name"`) avec l'identifiant (attribut `"id"`) : le premier sert à identifier les données qui sont soumises, le second à identifier des éléments dans la page en cours de visualisation. Seul l'identifiant est unique, deux éléments peuvent envoyer une donnée sous le même nom. Utiliser les mêmes valeurs pour les deux attributs vous épargnera toutefois beaucoup d'erreurs dans vos développements.

    <input type="text" name="nom" id="identifiant" />

#### Grouper les champs

Dans un formulaire avec plusieurs zones de saisies il est généralement de bon ton de regrouper les champs par catégories. On peut par exemple séparer les quelques champs qui vous demandent des informations sur votre situation familiale des champs qui demandent vos coordonnées bancaires. L'utilisateur en retirera une meilleure compréhension du formulaire et de son utilisation.

L'élément qui remplit ce rôle est `<fieldset>` . Il suffit de faire délimiter les données appartenant à un même groupe par cette balise. Toutefois, cet élément seul ne permet que de grouper certaines parties du formulaire, il ne renseigne pas sur l'utilité de la partie en question. Vous pouvez donc rajouter un élément `<legend>` à l'intérieur, son contenu servira de description au groupe.

    <form action="...">
    <fieldset>
      <legend>Adhérent</legend>
      <p><label>Nom : <input type="text" /></label></p>
      <p><label>Prénom : <input type="text" /></label></p>
    </fieldset>
    <fieldset>
      <legend>Conjoint(e)</legend>
      <p><label>Nom : <input type="text" /></label></p>
      <p><label>Prénom : <input type="text" /></label></p>
    </fieldset>
    </form>

Exemple d'utilisation de `<fieldset>` .

### Les autres types de données

La zone de saisie créée plus haut est intéressante mais est loin de couvrir tous les besoins d'une application Web. Voici une liste des différentes possibilités qui s'offrent à vous :

#### Zone de texte courte

La zone de texte courte est l'élément qui a été pris en exemple plus haut. Il s'agit d'une balise `<input>` avec l'attribut `type="text"`. Si l'attribut `"value"` est présent, il donne la valeur par défaut de la zone de saisie (`<input type="text" value="valeur par défaut" />`).

Vous pouvez définir la taille à l'affichage en spécifiant un nombre de caractères dans l'attribut `"size"`. Si l'utilisateur rentre une donnée plus longue il ne la verra pas en entier. Plus intéressant, vous pouvez aussi limiter la taille de la donnée grâce à l'attribut `"maxlength"` : `<input type="text" size="10" maxlength="20" />`. Faites tout de même attention au fait que cette limitation est faite pour empêcher l'utilisateur honnête de se tromper et de dépasser. Spécifier cet attribut n'empêchera pas l'utilisateur malhonnête d'envoyer une donnée trop longue volontairement.

Vous trouverez aussi deux attributs vides : `"readonly"` et `"disabled"`. Le premier, s'il est mis, indique que le contenu ne peut pas être changé par l'utilisateur mais seulement affiché. Le deuxième indique que le champ est totalement désactivé, il n'est pas éditable, ne reçoit pas le focus et n'est pas transmis pendant l'envoi du formulaire. Pour un document HTML il suffit de faire apparaître l'attribut (`<input type="text" disabled>`). Dans un document XHTML les attributs doivent avoir une valeur, il faut alors leur donner le nom de l'attribut comme valeur : `<input type="password" disabled="disabled" />`. Ces deux attributs sont communs à la plupart des champs de formulaire.

#### Mot de passe

Il existe un élément spécifique à la saisie de mot de passe. En spécifiant `type="password"` à la place de `type="text"` on obtient une zone qui affiche des étoiles à la place des caractères tapés. Cette saisie est appréciée pour les mots de passe, de façon à ce que l'assistance ne puisse pas lire à l'écran.

Attention toutefois : si vous spécifiez une valeur par défaut, même si elle apparaîtra sous forme d'étoiles dans la plupart des navigateurs, la valeur reste en clair dans le code source. Cela veut dire qu'il suffit de demander au navigateur d'afficher le code source pour connaître le mot de passe par défaut. De même, quelqu'un ayant accès au cache du navigateur, ou écoutant sur le réseau, pourra connaître ce mot de passe. La procédure ne protège donc que de ceux qui regardent l'écran en même temps que l'utilisateur, mais de rien ni de personne d'autre.

    <input type="password" value="en clair" />

Exemple de champ pour mot de passe.

#### Cases à cocher

Pour des séries d'options, il est possible de définir des cases à cocher (`type="checkbox"` à la place de `type="text"`). Ces cases ont un fonctionnement spécial : cochées elles envoient la valeur définie par l'attribut `"value"`, non cochées elles n'envoient rien (comme si elles n'étaient pas là). Il est possible de définir une case comme cochée par défaut en lui ajoutant un attribut vide nommé `"checked"` (`checked="checked"` en XHTML).

Il est fréquent de fournir une liste de cases à cocher pour poser des questions assez proches. N'oubliez alors pas de grouper ces différentes cases grâce à `<fieldset>` pour en faciliter la compréhension.

    <fieldset>
      <legend>Conditions générales</legend>

      <p><label>
        <input type="checkbox" value="OK" name="condgen" />
        J'ai lu les conditions générales du service
      </label></p>

      <p><label>
        <input type="checkbox" value="OK" name="spam" checked="checked" />
        J'autorise l'utilisation de mes coordonnées par la société
      </label></p>

    </fieldset>

Exemple de cases à cocher.

#### Zones d'options

Dans une série de cases à cocher, on aime souvent que l'utilisation d'une case désactive les autres pour sélectionner une option parmi plusieurs. Ces zones d'options (aussi appelées boutons radio) sont gérées par le type "radio". Le fonctionnement est similaire aux cases à cocher mais si plusieurs cases ont le même nom (attribut `"name"`) dans le formulaire, une seule pourra être activée à la fois (l'activation d'une case désactivera les autres).

Si le groupement des options lors de leur utilisation se fait par le nom, il est toujours conseillé de grouper aussi par `<fieldset>` pour permettre à l'utilisateur de prévoir ce fonctionnement et de le comprendre.

    <fieldset>
      <legend>Civilité</legend>
      <ul>
        <li><label>
          <input type="radio" value="monsieur" name="civilite" />
          Monsieur
        </label></li>
        <li><label>
          <input type="radio" value="madame" name="civilite" checked="checked" />
          Madame
        </label></li>
        <li><label>
          <input type="radio" value="mademoiselle" name="civilite" />
          Mademoiselle
        </label></li>
      </ul>
    </fieldset>

Exemple de zones d'options.

#### Listes de sélection

Les listes de sélection (balise `<select>` ) sont une autre manière de choisir entre plusieurs options. Quand l'attribut `"size"` n'est pas défini il s'agit d'une liste déroulante, sinon la zone est une liste de taille fixe (l'attribut définissant le nombre de choix à afficher à la fois). Si l'attribut `"multiple"` est défini il est possible pour l'utilisateur de choisir plusieurs options dans la liste (généralement avec les touches "control" et "shift" en plus de la méthode de sélection habituelle).

Les différents choix possibles sont définis par les balises `<option>` contenues dans le `<select>`. Chaque balise a un attribut `"value"` qui définit la valeur de l'option et contient sa description. Une option présélectionnée a de plus l'attribut `"selected"` de défini.

Si vous pouvez facilement faire plusieurs groupes distincts dans les options, il vous est recommandé de les grouper grâce à l'élément `<optgroup>` afin d'aider l'utilisateur à s'y retrouver. Il est similaire à `<fieldset>` mais au lieu d'avoir un sous élément `<legend>` il contient un attribut `"label"`. Ces groupes ne peuvent pas être imbriqués. Les navigateurs peuvent interpréter des groupes comme des sous menus ou comme des titres.

    <select name="pays">
      <optgroup label="Europe">
        <option value="fr" selected="selected">France</option>
        <option value="it">Italie</option>
      </optgroup>
      <optgroup label="Asie">
        <option value="ch">Chine</option>
      </optgroup>
    </select>

Exemple de liste déroulante.

#### Zone de texte longue

La zone de saisie `<input type="text">` vue préalablement n'est adaptée que pour des courtes chaînes et ne permet pas d'éditer simplement des textes sur plusieurs lignes. Pour cela il existe l'élément `<textarea>` . L'affichage sera un cadre de texte éditable, sa taille peut être définie par les attributs `"cols"` (nombre de caractère par ligne) et `"rows"` (nombre de lignes). Le texte défini par défaut est celui contenu entre la balise de début et la balise de fin. N'oubliez pas que ce texte ne remplace pas la balise `<label>`.

    <textarea cols="80" rows="4" name="article">
      Tapez ici votre article
    </textarea>

Exemple de zone de texte longue.

#### Fichiers

Il vous est possible d'envoyer des fichiers via les formulaires. L'élément `<input type="file" />` permettra à l'internaute de sélectionner un fichier local à envoyer. Si théoriquement l'attribut `"value"` peut définir l'emplacement par défaut du fichier, les navigateurs désactivent généralement cette possibilité pour des raisons de sécurité.

Vous pouvez restreindre le choix à une liste de types de contenu autorisés séparés par des virgules, en la spécifiant dans l'attribut `"accept"`. Les types de contenu sont les mêmes que ceux des entêtes HTTP `Content-Type` et `Accept`. On y trouve en vrac `text/plain` pour les textes, `text/html` pour le HTML, `application/xml` pour le XML, `image/png` pour les PNG, ou plus généralement `image/*` pour tous les types d'images. Le support par les navigateurs de cette propriété n'est malheureusement pas toujours très bon, il ne s'agit au plus que d'une aide pour l'utilisateur. Vous pouvez toutefois trouver une liste détaillée des types de contenu standardisés via la page de l'IANA sur les types MIME .

    <form action="..." accept="text/plain,text/html"><p>
      <label>Fichier à envoyer <input type="file" /></label>
    </p></form>

Exemple de soumission de fichier.

#### Valeurs cachées

Un dernier type de champ est possible pour transférer des données : des champs invisibles. Ces champs sont faits pour pouvoir définir sur la page des valeurs qui ne changeront pas ou qui n'ont pas besoin d'interactions directes avec l'utilisateur. Ils seront envoyés avec le formulaire au même titre que les autres champs. Il vous suffit de définir un élément `<input type="hidden" />` avec une valeur et un nom en attributs. Attention toutefois, ce n'est pas parce que le champ n'est pas visible dans le rendu que les valeurs ne peuvent pas être lues ou modifiées par le visiteur. Ne mettez rien de confidentiel ou ayant trait à la sécurité.

### Envoi du formulaire

#### Cible du formulaire

Un formulaire est habituellement destiné à être traité par un programme sur le serveur. L'attribut `"action"` permet de définir l'URI où sera envoyé le formulaire pour traitement. Cet attribut est le seul obligatoire.

Il existe deux manières d'envoyer le contenu d'un formulaire, gérées avec l'attribut `"method"` : post et get. Cette dernière se voit habituellement car les différentes valeurs du formulaire sont visibles dans l'adresse de la page résultante ; c'est la méthode utilisée par défaut. L'autre méthode fait passer les informations à envoyer dans le corps de la requête HTTP, et permet d'envoyer des informations plus conséquentes. Il vous est recommandé d'utiliser la méthode get quand aucune information envoyée n'est exagérément secrète (pas de mot de passe), que la quantité d'information est limitée et que deux soumissions avec les mêmes paramètres renvoient toujours la même information ; si un de ces trois critères n'est pas vérifié, vous devriez envisager la méthode post.

    <form action="http://www.domaine.ext/rep/script" method="post">
      <!-- contenu du formulaire -->
    </form>

Note : une erreur trés courante est d'écrire les valeurs de l'attribut `"method"` en majuscule. En fait, elles doivent être en minuscule : `method="get"` ou `method="post"`.

#### Déclenchement de l'envoi

Jusqu'à présent nous avons rempli notre formulaire mais nous n'avons toujours aucun élément permettant de déclencher l'envoi. En ajoutant un champ de type "submit" (`<input type="submit" />`) vous obtiendrez un bouton qui déclenche la soumission des données. Le texte par défaut du bouton est déterminé par le navigateur, vous pouvez le changer grâce à l'attribut `"value"`. Si ce bouton de validation a un nom (attribut `"name"`) et une valeur, cette valeur sera transmise lors de l'envoi ; une telle fonctionnalité permet d'utiliser plusieurs boutons et de déterminer lequel a été utilisé.

Exemple de bouton de soumission.

Il est aussi possible d'utiliser une image comme bouton d'envoi (`<input type="image" />`). Dans ce cas l'adresse de l'image devra être spécifiée via l'attribut `"src"` et un texte alternatif devra être fourni dans l'attribut `"alt"`, comme une image classique. Lorsque l'utilisateur envoie le formulaire en cliquant sur l'image, la position du clic dans l'image est envoyée en plus des données normales. Dans ce cas, la donnée "monimage.x" est la position horizontale en pixel et la donnée "monimage.y" est la position verticale, où "monimage" est le nom du champ de formulaire contenant l'image. Il est aussi possible de définir les zones réactives de l'image grâce aux attributs `"ismap"` et `"usemap"`, ces propriétés fonctionnent alors comme pour les images cliquables classiques.

#### Codage des données

Lorsqu'un formulaire est envoyé, les données sont codées de façon à ne pas perturber la requête HTTP. Le programme serveur qui reçoit les données doit pouvoir comprendre ce codage pour les relire. Vous pouvez, pour ce but, définir quel codage sera employé.

L'attribut `"enctype"` de l'élément `<form>` défini la façon de traiter les données. Par défaut la valeur est `application/x-www-form-urlencoded`. Vous devrez utiliser `multipart/form-data` si votre formulaire contient des fichiers à envoyer tels quels.

Pour finir, l'attribut `accept-charset` défini une liste de jeux de caractères utilisables pour l'envoi, séparés par des virgules ou espaces. Cette dernière propriété supporte des valeurs comme UTF-8 ou ISO-8859-1 mais pour compatibilité avec les navigateurs qui ne s'en servent pas, il est préférable de savoir gérer n'importe quel codage et de faire des conversions à la volée en se basant sur les entêtes HTTP

### Exemple complet

    <div>
    <form action="destination">

      <p>
        <label for="nom">Nom : </label>
        <input type="text" name="nom" id="nom" />
      </p>

      <p>
        <label for="prenom">Prénom : </label>
        <input type="text" name="prenom" id="prenom" />
      </p>

      <fieldset><legend>Sexe :</legend>
        <ul><li>
          <input type="radio" value="H" name="sexe" id="sH"/>
          <label for="sM">Homme</label>
        </li><li>
          <input type="radio" value="F" name="sexe" id="sF"/>
          <label for="sF">Femme</label>
        </li></ul>
      </fieldset>

      <p>
        <label for="pays">Pays : </label>
        <select name="pays">
          <optgroup label="Europe">
            <option value="fr">France</option>
            <option value="it">Italie</option>
          </optgroup>
          <optgroup label="Asie">
            <option value="ch">Chine</option>
          </optgroup>
        </select>
      </p>

    </form>
    </div>

### Notions d'accessibilité et d'usabilité

#### Descriptions

Comprendre un formulaire est souvent complexe pour des visiteurs sur navigateurs non graphiques. Pour ceux-ci une description complète du formulaire est une nécessité. Cela passe par l'utilisation de la balise `<label>` pour tous les champs, l'exploitation des groupes `<fieldset>` et `<optgroup>` dès que possible, mais aussi par la définition des zones dans une image cliquable grâce à l'attribut `"usemap"` et l'élément `<map>` (se reposer uniquement sur la position du clic rend la fonctionnalité inaccessible pour les navigateurs non graphiques ou avec un pointage alternatif).

Malheureusement tous les logiciels ne mettent pas à profit ces balisages. Il est donc important de vérifier la compréhension du formulaire lors d'une lecture linéaire : faire en sorte que la description suive ou précède toujours directement le champ décrit, et éviter de disperser les éléments du formulaire dans la page. Vous pouvez par exemple tester le rendu avec le navigateur Lynx pour vérifier que le formulaire, et le rôle de chaque élément, y sont compréhensibles.

#### Automatismes

Tous les visiteurs n'ont pas un navigateur configuré pour exécuter le javascript, il est donc nécessaire de permettre l'accès au formulaire sans scripts. L'ajout d'un bouton de soumission (`<input type="submit" value="envoyer"/>`) et une destination correctement remplie pour le formulaire sont indispensables. Les scripts pouvant, quant à eux, prendre la main en complément des éléments normaux lorsque le navigateur les supporte.

Dans le même esprit, si une validation des données par javascript peut être faite pour aider l'utilisateur à remplir les cases, elle ne remplace pas une validation par le programme sur le serveur car rien ne garanti que le visiteur utilise javascript et n'envoie pas les données directement.

Inversement, lorsque le javascript est supporté, il peut aussi limiter l'accessibilité du formulaire. C'est particulièrement le cas des scripts qui déclenchent automatiquement l'envoi après sélection d'une entrée (par exemple dans une liste déroulante) : certains logiciels ne permettent pas de naviguer dans une liste sans sélectionner un à un les éléments, ce qui activerait le javascript dès le premier élément et déclencherait l'action. Ces scripts de validation automatique sont donc à éviter.

#### Accès rapides

La structure est une chose, mais tel quel le formulaire n'est pas encore parfait pour un accès avec autre chose qu'une souris. Pour une meilleure accessibilité, il peut être intéressant de rajouter deux types d'éléments :

- Ajouter des combinaisons d'accès rapide. Avec un attribut `"accesskey"` sur quelques éléments spécifiques vous permettrez aux gens d'accéder directement à un élément du formulaire. C'est particulièrement valable pour des formulaires qui servent à la navigation, comme un formulaire de recherche.

- Ajouter un ordre d'accès. L'attribut `"tabindex"` permet de spécifier un ordre de parcours dans les champs de formulaire. Il doit contenir une valeur numérique entière, l'accès sera ordonné par cette valeur. Vous permettrez au visiteur d'accéder aux éléments dans l'ordre le plus pertinent, et leur évitez ainsi une recherche et un accès qui peuvent être longs ou complexes suivant leur handicap et logiciel.

#### Informations

L'accès technique au formulaire étant fait, il reste une dernière touche importante : aider l'utilisateur à se servir du formulaire.

Indiquez toujours si un champ est obligatoire, éventuellement par une simple ligne qui nomme les valeurs nécessaires au traitement si vous pensez qu'il serait trop lourd de le signaler à chaque fois.

Lorsqu'une erreur survient dans le traitement, indiquez précisément ce qui doit être fait comme correction et pointez la donnée manquante ou erronée. Renvoyez le message d'erreur sur la même page que le formulaire ; lui-même devant reproduire toutes les données entrées précédemment, ou conserver les données valides, et ne redemander que les manquantes ou erronées. L'utilisateur ne doit pas avoir à ressaisir les données correctement renseignées, ni à chercher où est son erreur.

Inversement, si aucune erreur n'apparaît, et à défaut d'une réponse spécifique, informez l'utilisateur que les données ont été reçues et traitées avec succès. Ne redirigez pas directement l'utilisateur vers la page d'accueil ou un nouveau formulaire vierge sans lui donner de confirmation sur le traitement du précédent.

### Le mot de la fin

Il y a encore beaucoup de choses à découvrir sur les formulaires, surtout sur l'ergonomie et les interactions avec l'utilisateur. Vous pouvez d'ailleurs trouver le détail des possibilités javascript de validation dans un article dédié.

S'il fallait mettre en avant un point de cet article afin de le garder à l'esprit, ce serait l'accessibilité. Les formulaires se révèlent souvent des barrières pour l'utilisateur, que ce soit celui qui n'est pas à l'aise avec l'informatique ou celui qui a de réelles difficultés d'accès au Web. Généralement quelques points simples permettent d'améliorer sensiblement la facilité d'utilisation de votre formulaire. On peut citer par exemple la présence des balises `<label>` ou le regroupement des champs et valeurs similaires (avec entre autres la balise `<fieldset>`).