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". 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" />
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 champ 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 champ 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 champ et sa description, et donc par exemple, un clic sur le label
ne mettra pas le focus sur le champ 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>
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>
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>
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éfinit 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="sH">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 garantit 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>
).
Vos commentaires
# Marc Le 16 avril 2014 à 03:05
Bonjour, y a-t-il une façon d’envoyer les information à une adresse courriel plutôt que de les enregistrer sur un serveur ?
Merci, Marc.
# jean-marc Fornasari Le 24 décembre 2014 à 16:44
excuser moi si je me trompe
# kjlkjlkj Le 9 septembre 2016 à 17:41
lklkjlkjlkjlkj
Vos commentaires
Suivre les commentaires : |