Précision: certains exemples fonctionneront dans d'autres navigateurs mais vous aurez besoin de Firefox 4 pour les voir tous.

Nouveaux types de champs

À l'instar des nouveaux éléments, HTML5 introduit de nouveaux types de champs pour mieux exprimer le genre d'informations que l'on souhaite recevoir. Le comportement et l'apparence de la plupart de ces nouveaux champs ne s'éloignent pas beaucoup du champ texte mais ils apportent un nouveau sens. Cela permet aux navigateurs de fournir une meilleure expérience aux utilisateurs. Par exemple, un navigateur mobile pourra fournir un clavier spécial pour certains champs[1]. Ou alors il pourra pré-remplir les champs téléphoniques en se basant sur votre carnet d'adresses. Et si ce n'est pas le navigateur, des extensions pourront imaginer d'autres usages en s'appuyant sur ces nouveaux champs.

Firefox 4 ajoute quatre nouveaux types de champs :

<input type="search">
<input type="tel">
<input type="url">
<input type="email">

Parmi ces quatre champs, url et email valideront aussi leur contenu. Mais on en parlera plus en détails plus loin.

Il y a aussi une nouvelle sorte de champ:

<output for="i1 i2">

Vous pouvez utiliser cet élément pour représenter une partie de la page qui réagit aux interactions avec le formulaire. Pensez au prix total dans un panier d'achats après avoir changé la quantité d'articles ou les options d'envoi. Ce champ ne calculera rien de lui-même, il faudra le faire avec JavaScript, mais cela donnera des indications aux technologies d'assistance. L'attribut for est la liste des ID des éléments qui ont participé au calcul.

Les champs textes ont été améliorés par le support de <datalist>. Cela permet de fournir une liste de suggestions à l'utilisateur pendant qu'il tape. On associe le champ et les suggestions en utilisant l'attribut list. Et pour les navigateurs qui ne supportent pas ce mécanisme, ils afficheront le contenu de l'élément <datalist>. Donc n'oubliez pas d'y mettre un balisage correct afin d'avoir une bonne dégradation.

ou
<label>Entrez une ville : <input list="cities"></label>
<datalist id="cities">
  ou
  <label>choisissez-en une
    <select>
      <option value="Paris">Paris</option>
      <option value="Londres">Londres</option>
      <option value="Berlin">Berlin</option>
      <option value="New York">New York</option>
      <option value="Tokyo">Tokyo</option>
      <option value="Sydney">Sydney</option>
      <option value="Johannesburg">Johannesburg</option>
      <option value="Melun">Melun</option>
    </select>
  </label>
</datalist>

Nouveaux attributs

Autofocus

Avec cet attribut sur un élément, il recevra le focus dès que possible. L'avantage direct pour l'utilisateur c'est que tous les sites utiliseront le même algorithme pour l'autofocus plutôt que d'avoir un bout de JavaScript différent sur chaque site. Et des navigateurs ou des extensions pourront facilement désactiver ce comportement si cela gêne l'utilisateur.

<input autofocus>

Placeholder

La valeur de cet attribut sera affichée lorsque le champ est vide et qu'il n'a pas le focus. Cela permet de donner un exemple de valeur attendue.

<label>Telephone: <input placeholder="+33 1 16 64 33 42"></label>
<label>Comments: <textarea placeholder="Dites nous ce que vous pensez de ce service…"></textarea></label>

Formulaires découplés[2]

Vous avez de nouvelles options pour configurer l'interaction entre les champs et les formulaires.

Attribut form

Les éléments <input> ne doivent plus obligatoirement être des enfants d'un élément <form>. Vous pouvez les définir où vous souhaitez et les rattacher à un formulaire en utilisant l'attribut form. Sa valeur est l'ID du formulaire auquel il doit se rattacher.

Voyons un exemple. Disons que vous travaillez sur un moteur de recherche pour un outil de blog. Vous voulez un formulaire très simple pour le cas général et quelques options avancées si l'utilisateur a besoin de plus de contrôle.

En haut de votre page, vous pouvez placer:

<input type="search" name="search_field" form="search_form">

Et plus bas:

<form id="search_form" action="search.php" method="post">
  <fieldset>
    <legend>Options avancées</legend>
    <input type="checkbox">Inclure les articles privés
    <!-- Autres options -->
  </fieldset>
</form>

Tout ceci se comportera comme si le champ de recherche faisait partie du formulaire. Mais vous avez la flexibilité de le placer où bon vous semble.

Les options de formulaires pour chaque champ

Toutes les options pouvant être définies au niveau du formulaire peuvent être redéfinies au niveau du champ. Tous les champs de soumissions (<button> et <input type="submit">) acceptent quatre nouveaux attributs : formenctype, formaction, formmethod et formtarget.

On peut imaginer les utiliser pour un formulaire avec des boutons publier et aperçu. Chacun a besoin des informations complètes du formulaire mais ils effectuent une action très différente.

<form action="new_post.php" method="post">
<label>Titre: <input type="text"></label>
<label>Contenu: <textarea></textarea></label>
<input type="submit" formaction="preview.php" formmethod="get" value="Aperçu">
<input type="submit" value="Publier">
</form>

Quand l'utilisateur clique sur le bouton Aperçu, ces attributs écraseront ceux du formulaire. Dans ce cas, au lieu d'une requête POST vers new_post.php, la totalité du formulaire sera soumise au script preview.php avec une méthode GET.

Mécanismes de validation

La validation est l'une des grandes améliorations des formulaires. Afin de fournir la meilleure expérience, il est de bon ton de donner un retour dès que possible à l'utilisateur. Du coup, chacun écrit beaucoup de JavaScript pour gérer cela. Ne serait-ce pas mieux que les navigateurs se débrouillent tous seuls ?

Depuis la parution de l'article original en novembre dernier, le style par défaut des champs invalides a été modifié et de nouvelles pseudo-classes ::-moz-ui-valid et ::-moz-ui-invalid ont été introduites. Du coup, les exemples ne sont plus aussi pertinents qu'à l'époque. Heureusement, Mounir a expliqué tous les changements.

required

Avec cet attribut, vous indiquez que ce champ est obligatoire. Pour les champs textes, cela signifie qu'ils ne doivent pas être vides. Pour les boutons checkbox, ils doivent être cochés. Et pour les boutons radios, l'un des boutons d'un groupe doit être sélectionné.

Essayez les exemples suivants pour voir les changements d'états.

<input type="text" required>
<input type="checkbox" required>
<input type="radio" name="radiogroup" required>
<input type="radio" name="radiogroup" required>
<input type="radio" name="radiogroup" required>

url

Les champs URLs sont automatiquement validés.

<input type="url" value="mozilla">
<input type="url" value="http://mozilla.org">

email

Les emails sont aussi validés automatiquement. En passant l'attribut multiple (utilisable sur type="file" aussi), il validera une liste d'emails séparés par des virgules.

<input type="email" value="foo">
<input type="email" value="foo@bar.org">
<input type="email" multiple value="foo@bar.org, spongebob">
<input type="email" multiple value="foo@bar.org, spongebob@squarepants.org">

pattern

Les URLs et les emails ne sont pas les seuls types de données que vous voulez valider. Pour cela, vous pouvez fournir une expression rationnelle JavaScript à l'attribut pattern. Elle sera utilisée pour valider la valeur d'un champ. Il est aussi conseillé de fournir un attribut title pour expliquer le type de contenu demandé.

Dans l'exemple suivant, survolez le champ. Vous devriez voir une aide vous expliquant comment remplir le champ.

<input pattern="[0-9][A-Z]{3}" title="A part number is a digit followed by three uppercase letters.">

L'API de validation des contraintes.

Si vous avez besoin d'encore un peu plus de contrôle sur la validation, vous pouvez utiliser la méthode setCustomValidity. Si vous l'appelez avec une chaîne vide, l'élément sera considéré comme valide. Sinon, il sera marqué invalide et la chaîne sera utilisée dans l'aide apparaissant pour l'utilisateur.

<label>Mot de passe : <input type="password" id="password1" oninput="checkPasswords()"></label>
<label>Confirmer mot de passe : <input type="password" id="password2" oninput="checkPasswords()"></label>
<script>
function checkPasswords() {
  var password1 = document.getElementById('password1');
  var password2 = document.getElementById('password2');
  if (password1.value != password2.value) {
    password2.setCustomValidity('Les mots de passe ne sont pas identiques');
  } else {
    password2.setCustomValidity('');
  }
}
</script>

Si l'un des champs dans un formulaire est invalide, la soumission du formulaire sera bloquée et le premier champ invalide sera mis en avant avec un message expliquant le problème. Si vous ne désirez pas ce comportement, vous pouvez ajouter l'attribut novalidate sur le formulaire ou l'attribut formnovalidate sur l'un des boutons de soumission.

Pour plus de détails sur le mécanisme de validation, je vous recommande l'article de Mounir.

Nouveaux sélecteurs CSS

Pour accompagner toutes ces magnifiques nouveautés, quelques nouveaux sélecteurs ne seront pas de trop.

:required, :optional

Tous les champs sont marqués :optional par défaut. S'ils ont l'attribut required, alors ils répondront à la pseudo-classe :required.

:valid, :invalid

Ces pseudos-classes représentent l'état de validation d'un champ. Vous pouvez utiliser :invalid pour redéfinir le style par défaut que Firefox 4 fournit.

Voici un exemple de champ avec le style par défaut modifié.

:-moz-placeholder

Cette pseudo-classe sélectionne les champs affichant un "placeholder". Ce n'est pas encore défini par CSS donc vous aurez besoin d'utiliser un pseudo-élément pour les navigateurs basés sur WebKit.

<style>
#selectors2 :-moz-placeholder {
  font-style: italic;
}
#selectors2 ::-webkit-placeholder {
  font-style: italic;
}
</style>
<form id="selectors2">
  <input placeholder="Donnez moi du style !">
</form>

Conclusion

Les fonctionnalités HTML5 des formulaires sont très récentes et il y a encore de grandes différences entre les navigateurs. Opera a implémenté une partie de la spécification (elle s'appelait encore Webforms2 à l'époque) donc le support est plutôt bon même si vous trouverez des différences étant donné que la spécification a évolué depuis. Les navigateurs basés sur WebKit sont actuellement en train d'implémenter donc vous trouverez un peu de support de ce côté là aussi.[3]

Il n'y aura pas d'autres nouveautés concernant les formulaires dans Firefox 4. Mais il y a encore beaucoup à faire pour avoir un support complet: de nouveaux types de champs (number, color, date), de nouveaux attributs (step, min, max), etc. Cela viendra dans de prochaines versions.

Ceci n'est qu'une vague introduction. Pour tous les détails, je recommande la documentation sur le Mozilla Developer Network.

Notes

[1] Voir mon article sur le comportement de l'iPhone. D'ailleurs, Firefox 4 aussi s'adapte.

[2] Je n'ai pas trouvé mieux pour exprimer cette idée.

[3] Honnêtement, c'est implémenté n'importe comment mais je ne vais pas m'étendre.