Dans cet article, nous verrons comment utiliser les CSS avec les formulaires HTML pour modifier le style de certains widgets difficiles à personnaliser. Comme nous l'avons vu dans l'article précédent, les champs texte et les boutons sont parfaitement compatibles avec les CSS. Maintenant, nous allons approfondir la part sombre de la composition stylistique des formulaires HTML.
-
-
Avant d'aller plus loin, faisons un rappel pour deux types de widgets de formulaires :
-
-
-
la brute
-
Éléments, dont le style n'est que difficilement modifiable, demandant des astuces complexes, nécessitant parfois de faire appel à une connaissance avancée des CSS3.
-
le truand
-
Oubliez l'emploi des CSS pour modifier le style de ces éléments. Au mieux, vous pourrez faire des petites choses, mais elle ne seront pas reproductibles sur d'autres navigateurs ; il ne sera jamais possible de prendre un contrôle total de leur apparence.
-
-
-
Possibilités d'expression avec les CSS
-
-
Le problème fondamental avec les widgets de formulaire, autres que champs de texte et boutons, est que dans de nombreux cas, le CSS ne possède pas assez d'expressions pour styliser correctement les widgets complexes.
-
-
L'évolution récente du HTML et des CSS a étendu l'expressivité des CSS :
-
-
-
CSS 2.1 était très limité et n'offrait que trois pseudo-classes :
-
-
-
{{cssxref(":active")}}
-
{{cssxref(":focus")}}
-
{{cssxref(":hover")}}
-
-
-
CSS Selector Level 3 a ajouté quelques nouvelles pseudo-classes relatives aux formulaires HTML :
-
-
{{cssxref(":enabled")}}
-
{{cssxref(":disabled")}}
-
{{cssxref(":checked")}}
-
{{cssxref(":indeterminate")}}
-
-
-
CSS Basic UI Level 3 a ajouté quelques autres pseudo-classes pour décrire l'état du widget :
-
-
{{cssxref(":default")}}
-
{{cssxref(":valid")}}
-
{{cssxref(":invalid")}}
-
{{cssxref(":in-range")}}
-
{{cssxref(":out-of-range")}}
-
{{cssxref(":required")}}
-
{{cssxref(":optional")}}
-
{{cssxref(":read-only")}}
-
{{cssxref(":read-write")}}
-
-
-
CSS Selector Level 4 actuellement en développement actif et objet de grandes discussions ne prévoit pas d'ajouter grand‑chose pour améliorer les formulaires :
-
-
{{cssxref(":user-error")}} qui est juste une amélioration de la pseudo‑classe {{cssxref(":invalid")}}.
-
-
-
-
-
Voilà un bon début, mais il y a deux problèmes. Primo, certains navigateurs ne mettent pas en œuvre des fonctionnalités au-delà de CSS 2.1. Secundo, ils ne sont tout simplement pas assez perfectionnés pour styliser des widgets complexes, comme les sélecteurs de date.
-
-
Il y a quelques expérimentations par les fournisseurs de navigateurs pour étendre l'expressivité des CSS sur les formulaires ; dans certains cas, il est bon de savoir ce qui est disponible..
-
-
-
Attention : Même si ces expérimentations sont intéressantes, elles ne sont pas normées, ce qui signifie qu'elles ne sont pas fiables. Si vous les utilisez (et vous ne devriez probablement pas le faire souvent), vous le faites à vos propres risques et périls ; vous faites quelque chose qui peut être mauvais pour le Web en utilisant des propriétés non standard.
Les navigateurs fondés sur WebKit- (Chrome, Safari) et Gecko- (Firefox) offrent les meilleures possibilités de personnalisation des widgets HTML. Ils sont aussi disponibles sur plateforme croisées, et donc ils nécessitent un mécanisme de bascule entre les widgets de « look and feel » natif et widget stylistiquement composables par l'utilisateur.
-
-
À cette fin, ils utilisent une propriété propriétaire : {{cssxref("-webkit-appearance")}} ou {{cssxref("appearance")}}. Ces propriétés ne sont pas normées et ne doivent pas être utilisées. En fait, elles se comportent même différemment entre WebKit et Gecko. Cependant, il y a une valeur qu'il est bon de connaître : none. Avec cette valeur, vous êtes en mesure d'obtenir un contrôle (presque total) sur le style des widgets donnés.
-
-
Donc, si vous avez du mal à appliquer un style à un élément, essayez d'utiliser ces propriétés propriétaires. Nous verrons quelques exemples ci-dessous, mais le cas d'utilisation le plus connu de cette propriété est relatif au style des champs de recherche sur les navigateurs WebKit :
-
-
<style>
+{{LearnSidebar}}{{PreviousMenuNext("Web/Guide/HTML/Formulaires/Apparence_des_formulaires_HTML", "Web/Guide/HTML/Formulaires/Property_compatibility_table_for_form_widgets", "Web/Guide/HTML/Formulaires")}}
+
+Dans cet article, nous verrons comment utiliser les [CSS](/fr/docs/Learn/CSS) avec les formulaires [HTML](/fr/docs/Glossary/HTML) pour modifier le style de certains widgets difficiles à personnaliser. Comme nous l'avons vu dans l'[article précédent](/fr/docs/Learn/Forms/Styling_web_forms), les champs texte et les boutons sont parfaitement compatibles avec les CSS. Maintenant, nous allons approfondir la part sombre de la composition stylistique des formulaires HTML.
+
+Avant d'aller plus loin, faisons un rappel pour deux types de widgets de formulaires :
+
+- la brute
+ - : Éléments, dont le style n'est que difficilement modifiable, demandant des astuces complexes, nécessitant parfois de faire appel à une connaissance avancée des CSS3.
+- le truand
+ - : Oubliez l'emploi des CSS pour modifier le style de ces éléments. Au mieux, vous pourrez faire des petites choses, mais elle ne seront pas reproductibles sur d'autres navigateurs ; il ne sera jamais possible de prendre un contrôle total de leur apparence.
+
+## Possibilités d'expression avec les CSS
+
+Le problème fondamental avec les widgets de formulaire, autres que champs de texte et boutons, est que dans de nombreux cas, le CSS ne possède pas assez d'expressions pour styliser correctement les widgets complexes.
+
+L'évolution récente du HTML et des CSS a étendu l'expressivité des CSS :
+
+- [CSS 2.1](https://www.w3.org/TR/CSS21/selector.html#dynamic-pseudo-classes) était très limité et n'offrait que trois pseudo-classes :
+
+ - {{cssxref(":active")}}
+ - {{cssxref(":focus")}}
+ - {{cssxref(":hover")}}
+
+- [CSS Selector Level 3](https://www.w3.org/TR/css3-selectors/) a ajouté quelques nouvelles pseudo-classes relatives aux formulaires HTML :
+
+ - {{cssxref(":enabled")}}
+ - {{cssxref(":disabled")}}
+ - {{cssxref(":checked")}}
+ - {{cssxref(":indeterminate")}}
+
+- [CSS Basic UI Level 3](https://dev.w3.org/csswg/css3-ui/#pseudo-classes) a ajouté quelques autres pseudo-classes pour décrire l'état du widget :
+
+ - {{cssxref(":default")}}
+ - {{cssxref(":valid")}}
+ - {{cssxref(":invalid")}}
+ - {{cssxref(":in-range")}}
+ - {{cssxref(":out-of-range")}}
+ - {{cssxref(":required")}}
+ - {{cssxref(":optional")}}
+ - {{cssxref(":read-only")}}
+ - {{cssxref(":read-write")}}
+
+- [CSS Selector Level 4](https://dev.w3.org/csswg/selectors4/) actuellement en développement actif et objet de grandes discussions ne prévoit pas d'ajouter grand‑chose pour améliorer les formulaires :
+
+ - {{cssxref(":user-error")}} qui est juste une amélioration de la pseudo‑classe {{cssxref(":invalid")}}.
+
+Voilà un bon début, mais il y a deux problèmes. Primo, certains navigateurs ne mettent pas en œuvre des fonctionnalités au-delà de CSS 2.1. Secundo, ils ne sont tout simplement pas assez perfectionnés pour styliser des widgets complexes, comme les sélecteurs de date.
+
+Il y a quelques expérimentations par les fournisseurs de navigateurs pour étendre l'expressivité des CSS sur les formulaires ; dans certains cas, il est bon de savoir ce qui est disponible..
+
+> **Attention :** Même si ces expérimentations sont intéressantes, **elles ne sont pas normées, ce qui signifie qu'elles ne sont pas fiables**. Si vous les utilisez (et vous ne devriez probablement pas le faire souvent), vous le faites à vos propres risques et périls ; [vous faites quelque chose qui peut être mauvais pour le Web](https://www.alistapart.com/articles/every-time-you-call-a-proprietary-feature-css3-a-kitten-dies/) en utilisant des propriétés non standard.
+
+- [Extensions des CSS Mozilla](/fr/docs/CSS/CSS_Reference/Mozilla_Extensions "/en-US/docs/CSS/CSS_Reference/Mozilla_Extensions")
+
+ - {{cssxref(":placeholder-shown")}}
+ - {{cssxref(":-moz-submit-invalid")}}
+ - {{cssxref(":user-invalid")}}
+ - {{cssxref(":-moz-ui-valid")}}
+
+- [Extensions des CSS WebKit](/fr/docs/CSS/CSS_Reference/Webkit_Extensions "/en-US/docs/CSS/CSS_Reference/Webkit_Extensions")
+
+ - {{cssxref("::-webkit-input-placeholder")}}
+ - [et beaucoup d'autres](http://trac.webkit.org/wiki/Styling%20Form%20Controls)
+
+- [Extensions des CSS Microsoft](http://msdn.microsoft.com/en-us/library/ie/hh869403%28v=vs.85%29.aspx)
+
+ - [`:-ms-input-placeholder`](http://msdn.microsoft.com/en-us/library/ie/hh772745%28v=vs.85%29.aspx)
+
+### Contrôle du style des éléments de formulaire
+
+Les navigateurs fondés sur WebKit- (Chrome, Safari) et Gecko- (Firefox) offrent les meilleures possibilités de personnalisation des widgets HTML. Ils sont aussi disponibles sur plateforme croisées, et donc ils nécessitent un mécanisme de bascule entre les widgets de « look and feel » natif et widget stylistiquement composables par l'utilisateur.
+
+À cette fin, ils utilisent une propriété propriétaire : {{cssxref("-webkit-appearance")}} ou {{cssxref("appearance")}}. **Ces propriétés ne sont pas normées et ne doivent pas être utilisées**. En fait, elles se comportent même différemment entre WebKit et Gecko. Cependant, il y a une valeur qu'il est bon de connaître : `none`. Avec cette valeur, vous êtes en mesure d'obtenir un contrôle (presque total) sur le style des widgets donnés.
+
+Donc, si vous avez du mal à appliquer un style à un élément, essayez d'utiliser ces propriétés propriétaires. Nous verrons quelques exemples ci-dessous, mais le cas d'utilisation le plus connu de cette propriété est relatif au style des champs de recherche sur les navigateurs WebKit :
+
+```html
+
-<form>
- <input type="search">
-</form>
Note : Il est toujours difficile de prédire l'avenir, quand on parle de techniques Web. L'extension des possibilités d'expression des CSS est difficile ; il y a un travail exploratoire avec d'autres spécifications, telles que Shadow DOM qui offrent certaines perspectives. La quête du formulaire de style totalement composable est loin d'être terminée.
-
+> **Note :** Il est toujours difficile de prédire l'avenir, quand on parle de techniques Web. L'extension des possibilités d'expression des CSS est difficile ; il y a un travail exploratoire avec d'autres spécifications, telles que [Shadow DOM](https://dvcs.w3.org/hg/webcomponents/raw-file/tip/spec/shadow/index.html) qui offrent certaines perspectives. La quête du formulaire de style totalement composable est loin d'être terminée.
-
Exemples
+## Exemples
-
Cases à cocher et boutons radio
+### Cases à cocher et boutons radio
-
Composer le style d'une case à cocher ou d'un bouton radio conduit à un certain désordre en soi. Par exemple, la taille des cases à cocher et des boutons radio n'est pas vraiment destinée à être modifiée et les navigateurs peuvent réagir très différemment, si vous essayez de le faire.
+Composer le style d'une case à cocher ou d'un bouton radio conduit à un certain désordre en soi. Par exemple, la taille des cases à cocher et des boutons radio n'est pas vraiment destinée à être modifiée et les navigateurs peuvent réagir très différemment, si vous essayez de le faire.
-
Voici les différentes façons dont divers navigateurs gèrent cela :
-
-
-
-
-
Navigateur
-
Rendu
-
-
-
-
-
Firefox 57 (Mac OSX)
-
-
-
-
Firefox 57 (Windows 10)
-
-
-
-
Chrome 63 (Mac OSX)
-
-
-
-
Chrome 63 (Windows 10)
-
-
-
-
Opera 49 (Mac OSX)
-
-
-
-
Internet Explorer 11 (Windows 10)
-
-
-
-
Edge 16 (Windows 10)
-
-
-
-
-
-
Un exemple un peu plus compliqué
-
-
Comme Opera et Internet Explorer n'ont pas de fonctionnalités telles que {{cssxref("-webkit-appearance")}} ou {{cssxref("appearance")}}, leur utilisation n'est pas appropriée. Heureusement, nous sommes dans un cas où les CSS disposent d'assez d'expressions pour trouver des solutions. Prenons un exemple courant :
body {
+}
+```
+
+Voici les différentes façons dont divers navigateurs gèrent cela :
+
+| Navigateur | Rendu |
+| --------------------------------- | --------------------------------- |
+| Firefox 57 (Mac OSX) |  |
+| Firefox 57 (Windows 10) |  |
+| Chrome 63 (Mac OSX) |  |
+| Chrome 63 (Windows 10) |  |
+| Opera 49 (Mac OSX) |  |
+| Internet Explorer 11 (Windows 10) |  |
+| Edge 16 (Windows 10) |  |
+
+#### Un exemple un peu plus compliqué
+
+Comme Opera et Internet Explorer n'ont pas de fonctionnalités telles que {{cssxref("-webkit-appearance")}} ou {{cssxref("appearance")}}, leur utilisation n'est pas appropriée. Heureusement, nous sommes dans un cas où les CSS disposent d'assez d'expressions pour trouver des solutions. Prenons un exemple courant :
+
+```html
+
Maintenant composons pour avoir une case à cocher personnalisée.
+Maintenant composons pour avoir une case à cocher personnalisée.
-
Le plan consiste à remplacer la case à cocher native par une image de notre choix. Tout d'abord, nous devons préparer une image avec tous les états requis pour une case à cocher. Ces états sont : non coché, coché, non coché désactivé et coché désactivé. Cette image sera utilisée comme fantôme des CSS :
+Le plan consiste à remplacer la case à cocher native par une image de notre choix. Tout d'abord, nous devons préparer une image avec tous les états requis pour une case à cocher. Ces états sont : non coché, coché, non coché désactivé et coché désactivé. Cette image sera utilisée comme fantôme des CSS :
-
+
-
Commençons par masquer les cases à cocher d'origine. Nous les déplacerons simplement à l'extérieur de la fenêtre de visualisation de la page. Il y a deux choses importantes à considérer ici :
+Commençons par masquer les cases à cocher d'origine. Nous les déplacerons simplement à l'extérieur de la fenêtre de visualisation de la page. Il y a deux choses importantes à considérer ici :
-
-
N'utilisez pas display:none pour masquer la case à cocher, car comme nous le verrons ci-dessous, nous avons besoin que la case à cocher soit disponible pour l'utilisateur. Avec display:none, la case à cocher n'est plus accessible à l'utilisateur, ce qui signifie qu'il est impossible de la cocher ou de la décocher.
-
Nous utiliserons quelques sélecteurs CSS3 pour réaliser notre style. Afin de prendre en charge les navigateurs existants, nous pouvons préfixer tous nos sélecteurs avec la pseudo-classe {{cssxref(":root")}}. Dans l'état actuel des implémentations, tous les navigateurs prenant en charge ce dont nous avons besoin prenent en charge également la pseudo-classe {{cssxref(":root")}}, mais d'autres ne le font pas. Ceci est un exemple de moyen pratique pour filtrer l'ancien Internet Explorer. Ces anciens navigateurs verront la case à cocher normale tandis que les navigateurs modernes verront la case à cocher personnalisée.
-
+- N'utilisez pas `display:none` pour masquer la case à cocher, car comme nous le verrons ci-dessous, nous avons besoin que la case à cocher soit disponible pour l'utilisateur. Avec `display:none`, la case à cocher n'est plus accessible à l'utilisateur, ce qui signifie qu'il est impossible de la cocher ou de la décocher.
+- Nous utiliserons quelques sélecteurs CSS3 pour réaliser notre style. Afin de prendre en charge les navigateurs existants, nous pouvons préfixer tous nos sélecteurs avec la pseudo-classe {{cssxref(":root")}}. Dans l'état actuel des implémentations, tous les navigateurs prenant en charge ce dont nous avons besoin prenent en charge également la pseudo-classe {{cssxref(":root")}}, mais d'autres ne le font pas. Ceci est un exemple de moyen pratique pour filtrer l'ancien Internet Explorer. Ces anciens navigateurs verront la case à cocher normale tandis que les navigateurs modernes verront la case à cocher personnalisée.
-
:root input[type=checkbox] {
+```css
+:root input[type=checkbox] {
/* les cases à cocher d'origine sont placées en dehors de la vue */
position: absolute;
left: -1000em;
-}
+}
+```
-
Maintenant que nous sommes débarrassés des cases à cocher natives, ajoutons la nôtre. Pour cela, nous utiliserons le pseudo élément {{cssxref("::before")}} de l'élément {{HTMLElement("label")}} qui suit la case à cocher originale. Ainsi, dans le sélecteur suivant, nous utilisons le sélecteur d'attributs pour cibler la case à cocher, puis nous utilisons le sélecteur de parents adjacent pour cibler le label suivant la case à cocher originale. Enfin, nous accédons au pseudo-élément {{cssxref("::before")}} et le styliser pour qu'il affiche notre case à cocher personnalisée non cochée.
+Maintenant que nous sommes débarrassés des cases à cocher natives, ajoutons la nôtre. Pour cela, nous utiliserons le pseudo élément {{cssxref("::before")}} de l'élément {{HTMLElement("label")}} qui suit la case à cocher originale. Ainsi, dans le sélecteur suivant, nous utilisons le sélecteur d'attributs pour cibler la case à cocher, puis nous utilisons le sélecteur de parents adjacent pour cibler le `label` suivant la case à cocher originale. Enfin, nous accédons au pseudo-élément {{cssxref("::before")}} et le styliser pour qu'il affiche notre case à cocher personnalisée non cochée.
-
Nous utilisons les pseudo-classes {{cssxref(":checked")}} et {{cssxref(":disabled")}} sur la case à cocher d'origine pour changer l'état de notre case à cocher personnalisée en conséquence. Comme nous utilisons un fantôme des CSS, tout ce que nous avons à faire est de changer la position de l'arrière-plan.
+Nous utilisons les pseudo-classes {{cssxref(":checked")}} et {{cssxref(":disabled")}} sur la case à cocher d'origine pour changer l'état de notre case à cocher personnalisée en conséquence. Comme nous utilisons un fantôme des CSS, tout ce que nous avons à faire est de changer la position de l'arrière-plan.
-
Une dernière chose (mais très importante) : lorsqu'un utilisateur utilise le clavier pour naviguer d'un widget à un autre, chaque widget qui reçoit le focus doit être marqué visuellement. Comme nous cachons les cases à cocher natives, nous devons implémenter cette fonctionnalité nous-mêmes : l'utilisateur doit pouvoir voir où elles se trouvent dans le formulaire. Le CSS suivant met en œuvre le focus sur les cases à cocher personnalisées.
+Une dernière chose (mais très importante) : lorsqu'un utilisateur utilise le clavier pour naviguer d'un widget à un autre, chaque widget qui reçoit le focus doit être marqué visuellement. Comme nous cachons les cases à cocher natives, nous devons implémenter cette fonctionnalité nous-mêmes : l'utilisateur doit pouvoir voir où elles se trouvent dans le formulaire. Le CSS suivant met en œuvre le focus sur les cases à cocher personnalisées.
-
Comme nous avons vu dans les exemples précédents, à chaque fois qu'un utilisateur tente d'envoyer un formulaire invalide, le navigateur affiche un message d'erreur. La manière dont le message est affiché dépend du navigateur.
-
-
Ces messages automatiques présentent deux inconvénients:
-
-
-
Il n'y a pas de façon standard de changer leur apparence avec CSS.
-
Ils dépendent des paramètres régionaux du navigateur, ce qui signifie que vous pouvez avoir une page dans une langue mais les messages d'erreurs affichés dans une autre.
-
-
-
-
Versions françaises des navigateurs sur une page en anglais
-
-
-
Navigateur
-
Affichage
-
-
-
-
-
Firefox 17 (Windows 7)
-
-
-
-
Chrome 22 (Windows 7)
-
-
-
-
Opera 12.10 (Mac OSX)
-
-
-
-
+}
+```
+
+{{EmbedLiveSample("Exemple_complet", "100%", 450)}}
+
+### Messages adaptés pour les erreurs
-
Pour personnaliser l'apparence et le texte de ces messages, vous devez utiliser JavaScript ; il n'est pas possible de l'implémenter en utilisant uniquement HTML et CSS.
+Comme nous avons vu dans les exemples précédents, à chaque fois qu'un utilisateur tente d'envoyer un formulaire invalide, le navigateur affiche un message d'erreur. La manière dont le message est affiché dépend du navigateur.
-
HMTL5 fournit une API de contraintes de validation pour vérifier et personnaliser l'état des élément d'un formulaire. Il est possible, entre autres, de changer le texte des messages d'erreur. Voici un court exemple :
+Ces messages automatiques présentent deux inconvénients:
-
<form>
- <label for="mail">Pourriez-vous nous fournir une adresse mail ?</label>
- <input type="email" id="mail" name="mail">
- <button>Envoyer</button>
-</form>
+- Il n'y a pas de façon standard de changer leur apparence avec CSS.
+- Ils dépendent des paramètres régionaux du navigateur, ce qui signifie que vous pouvez avoir une page dans une langue mais les messages d'erreurs affichés dans une autre.
-
+| Navigateur | Affichage |
+| ---------------------- | ------------------------------------------------------------------------------------------------ |
+| Firefox 17 (Windows 7) |  |
+| Chrome 22 (Windows 7) |  |
+| Opera 12.10 (Mac OSX) |  |
-
var email = document.getElementById("mail");
+Pour personnaliser l'apparence et le texte de ces messages, vous devez utiliser JavaScript ; il n'est pas possible de l'implémenter en utilisant uniquement HTML et CSS.
+
+HMTL5 fournit une [API de contraintes de validation](https://www.w3.org/TR/html5/forms.html#the-constraint-validation-api) pour vérifier et personnaliser l'état des élément d'un formulaire. Il est possible, entre autres, de changer le texte des messages d'erreur. Voici un court exemple :
+
+```html
+
+```
+
+En JavaScript, il faut appeler la méthode [`setCustomValidity()`]( "/en-US/docs/HTML/HTML5/Constraint_validation#Constraint_API's_element.setCustomValidity()"):
+
+```js
+var email = document.getElementById("mail");
email.addEventListener("keyup", function (event) {
if(email.validity.typeMismatch) {
@@ -397,126 +379,72 @@ email.addEventListener("keyup", function (event) {
} else {
email.setCustomValidity("");
}
-});
-
-
Si vous souhaitez avoir le contrôle de l'apparence des messages d'erreur, ou si vous voulez gérer le comportement des navigateurs n'ayant pas implémenté la validation de formulaire HTML5, vous n'avez pas d'autre choix que d'utiliser JavaScript.
-
-
API de contraintes de validation HTML5
-
-
De plus en plus de navigateurs prennent maintenant en charge l'API de validation des contraintes, et elle devient fiable. Cette API se compose d'un ensemble de méthodes et de propriétés disponibles sur chaque élément de formulaire.
-
-
Propriétés de l'API de validation des contraintes
-
-
-
-
-
Propriétés
-
Description
-
-
-
-
-
validationMessage
-
Un message (dans la langue locale) décrivant les contraintes de validation que le contrôle ne satisfait pas (si c'est le cas), ou une chaîne vide si le contrôle n'est pas soumis à validation (willValidate est alors false), ou bien la valeur de l'élément satisfait ses contraintes.
-
-
-
validity
-
Un objet {{domxref("ValidityState")}} qui décrit l'état de validité de l'élément.
-
-
-
validity.customError
-
Renvoie true si l'élément à une erreur personnalisée, false a contrario.
-
-
-
validity.patternMismatch
-
Renvoie true si la valeur de l'élément ne correspond pas au motif fourni, false dans le cas contraire. Si la méthode renvoie true, l'élément fera partie de la pseudo-classe CSS {{cssxref(":invalid")}}.
-
-
-
validity.rangeOverflow
-
Renvoie true si la valeur de l'élément est supérieure au maximum défini, false dans le cas contraire. Si le retour est true, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}.
-
-
-
validity.rangeUnderflow
-
Renvoie true si la valeur de l'élément est plus petite que le minimum défini, false dans le cas contraire. Si le retour est true, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}.
-
-
-
validity.stepMismatch
-
Renvoie true si la valeur de l'élément ne correspond pas aux règles définies par l'attribut step,false a contrario. Si le retour est true, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}.
-
-
-
validity.tooLong
-
Renvoie true si la taille de l'élément est supérieure à la longueur maximum définie, false dans le cas contraire. Si le retour est true, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}.
-
-
-
validity.typeMismatch
-
Renvoie true si la syntaxe de la valeur de l'élément n'est pas correcte ; false dans le cas contraire. Si le retour est true, l'élément sera de la pseudo-classe CSS {{cssxref(":invalid")}}.
-
-
-
validity.valid
-
Renvoie true si la valeur de l'élément n'a pas de problème de validité, sinon false. L'élément sera de la pseudo-classe CSS {{cssxref(":valid")}} si le retour est true ; de la pseudo-classe CSS {{cssxref(":invalid")}} si le retour est false.
-
-
-
validity.valueMissing
-
Renvoie true si l'élément n'a pas de valeur alors que le champ est requis, sinonfalse. L'élément sera de la pseudo-classe CSS {{cssxref(":invalid")}} si le retour est true.
-
-
-
willValidate
-
Retourne true si l'élément est validé lorsque le formulaire est soumis, false dans le cas contraire.
-
-
-
+});
+```
-
Méthodes de l'API de validation des contraintes
-
-
-
-
-
Méthodes
-
Description
-
-
-
-
-
checkValidity()
-
Renvoie true si la valeur de l'élément n'a pas de problème de validation, false autrement. Si l'élément est invalide, cette méthode déclenche aussi un événement {{event("invalid")}} sur cet élément.
-
-
-
setCustomValidity(message)
-
Ajoute un message d'erreur personnalisé à l'élément ; si vous définissez un message d'erreur personnalisé, l'élément est considéré comme invalide, et le message spécifié est affiché. Cela vous permet d'utiliser du code JavaScript pour établir une erreur de validation autre que celles offertes par l'API standard des contraintes de validation. Le message est affiché à l'utilisateur lorsque le problème est rapporté. Si l'argument est une chaîne de caractères vide, l'erreur personnalisée est considérée comme effacée.
-
-
-
+{{EmbedLiveSample("Messages_adaptés_pour_les_erreurs", "100%", 50)}}
+
+## Validation de formulaires avec JavaScript
+
+Si vous souhaitez avoir le contrôle de l'apparence des messages d'erreur, ou si vous voulez gérer le comportement des navigateurs n'ayant pas implémenté la validation de formulaire HTML5, vous n'avez pas d'autre choix que d'utiliser JavaScript.
+
+### API de contraintes de validation HTML5
+
+De plus en plus de navigateurs prennent maintenant en charge l'API de validation des contraintes, et elle devient fiable. Cette API se compose d'un ensemble de méthodes et de propriétés disponibles sur chaque élément de formulaire.
+
+Propriétés de l'API de validation des contraintes
+
+| Propriétés | Description |
+| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `validationMessage` | Un message (dans la langue locale) décrivant les contraintes de validation que le contrôle ne satisfait pas (si c'est le cas), ou une chaîne vide si le contrôle n'est pas soumis à validation (`willValidate` est alors `false`), ou bien la valeur de l'élément satisfait ses contraintes. |
+| `validity` | Un objet {{domxref("ValidityState")}} qui décrit l'état de validité de l'élément. |
+| `validity.customError` | Renvoie `true` si l'élément à une erreur personnalisée, `false` a contrario. |
+| `validity.patternMismatch` | Renvoie `true` si la valeur de l'élément ne correspond pas au motif fourni, `false` dans le cas contraire. Si la méthode renvoie `true`, l'élément fera partie de la pseudo-classe CSS {{cssxref(":invalid")}}. |
+| `validity.rangeOverflow` | Renvoie `true` si la valeur de l'élément est supérieure au maximum défini, `false` dans le cas contraire. Si le retour est `true`, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}. |
+| `validity.rangeUnderflow` | Renvoie `true` si la valeur de l'élément est plus petite que le minimum défini, `false` dans le cas contraire. Si le retour est `true`, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}. |
+| `validity.stepMismatch` | Renvoie `true` si la valeur de l'élément ne correspond pas aux règles définies par l'attribut `step`,`false` a contrario. Si le retour est `true`, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}. |
+| `validity.tooLong` | Renvoie `true` si la taille de l'élément est supérieure à la longueur maximum définie, `false` dans le cas contraire. Si le retour est `true`, l'élément fera partie des pseudo-classes CSS {{cssxref(":invalid")}} et {{cssxref(":out-of-range")}}. |
+| `validity.typeMismatch` | Renvoie `true` si la syntaxe de la valeur de l'élément n'est pas correcte ; `false` dans le cas contraire. Si le retour est `true`, l'élément sera de la pseudo-classe CSS {{cssxref(":invalid")}}. |
+| `validity.valid` | Renvoie `true` si la valeur de l'élément n'a pas de problème de validité, sinon `false`. L'élément sera de la pseudo-classe CSS {{cssxref(":valid")}} si le retour est `true` ; de la pseudo-classe CSS {{cssxref(":invalid")}} si le retour est `false`. |
+| `validity.valueMissing` | Renvoie `true` si l'élément n'a pas de valeur alors que le champ est requis, sinon`false`. L'élément sera de la pseudo-classe CSS {{cssxref(":invalid")}} si le retour est `true`. |
+| `willValidate` | Retourne `true` si l'élément est validé lorsque le formulaire est soumis, `false` dans le cas contraire. |
+
+#### Méthodes de l'API de validation des contraintes
+
+| Méthodes | Description |
+| ---------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `checkValidity()` | Renvoie `true` si la valeur de l'élément n'a pas de problème de validation, `false` autrement. Si l'élément est invalide, cette méthode déclenche aussi un événement {{event("invalid")}} sur cet élément. |
+| `setCustomValidity(message)` | Ajoute un message d'erreur personnalisé à l'élément ; si vous définissez un message d'erreur personnalisé, l'élément est considéré comme invalide, et le message spécifié est affiché. Cela vous permet d'utiliser du code JavaScript pour établir une erreur de validation autre que celles offertes par l'API standard des contraintes de validation. Le message est affiché à l'utilisateur lorsque le problème est rapporté. Si l'argument est une chaîne de caractères vide, l'erreur personnalisée est considérée comme effacée. |
-
Pour les anciens navigateurs, il existe une prothèse d'émulation (polyfill) comme Hyperform, pour compenser le défaut de prise en charge de cette API. Comme vous utilisez déjà JavaScript, l'utilisation d'une prethèse d'émulation n'est pas un souci supplémentaire pour la conception ou l'implémentation de votre site ou application Web.
+Pour les anciens navigateurs, il existe [une prothèse d'émulation (_polyfill_) comme Hyperform](https://hyperform.js.org/), pour compenser le défaut de prise en charge de cette API. Comme vous utilisez déjà JavaScript, l'utilisation d'une prethèse d'émulation n'est pas un souci supplémentaire pour la conception ou l'implémentation de votre site ou application Web.
-
Exemple utilisant la validation des contraintes
+#### Exemple utilisant la validation des contraintes
-
Voyons comment utiliser l'API pour créer des messages d'erreur personnalisés. Tout d'abord, le HTML :
+Voyons comment utiliser l'API pour créer des messages d'erreur personnalisés. Tout d'abord, le HTML :
-
Ce formulaire simple utilise l'attribut {{htmlattrxref("novalidate","form")}} pour désactiver la validation automatique par le navigateur ; cela permet donc à notre script d'avoir le contrôle sur la validation. Toutefois, cela ne désactive la prise en charge par l'API de validation des contraintes, ni l'application des pseudo-classes CSS {{cssxref(":valid")}}, {{cssxref(":invalid")}}, {{cssxref(":in-range")}} et {{cssxref(":out-of-range")}}. Cela signifie que, même si le navigateur ne vérifie pas automatiquement la validité du formulaire avant l'envoi des données, vous pouvez toujours effectuer cette validation et définir l'apparence du formulaire par vous-même.
+Ce formulaire simple utilise l'attribut {{htmlattrxref("novalidate","form")}} pour désactiver la validation automatique par le navigateur ; cela permet donc à notre script d'avoir le contrôle sur la validation. Toutefois, cela ne désactive la prise en charge par l'API de validation des contraintes, ni l'application des pseudo-classes CSS {{cssxref(":valid")}}, {{cssxref(":invalid")}}, {{cssxref(":in-range")}} et {{cssxref(":out-of-range")}}. Cela signifie que, même si le navigateur ne vérifie pas automatiquement la validité du formulaire avant l'envoi des données, vous pouvez toujours effectuer cette validation et définir l'apparence du formulaire par vous-même.
-
L'attribut aria-live garantit que nos messages d'erreur personnalisés seront affichés à tout le monde, y compris les personnes utilisant des techniques d'assistance comme des lecteurs d'écran.
+L'attribut [`aria-live`](/fr/docs/Accessibility/ARIA/ARIA_Live_Regions) garantit que nos messages d'erreur personnalisés seront affichés à tout le monde, y compris les personnes utilisant des techniques d'assistance comme des lecteurs d'écran.
-
CSS
+##### CSS
-
Ce CSS compose le formulaire et les messages d'erreur pour les rendre plus attrayants.
+Ce CSS compose le formulaire et les messages d'erreur pour les rendre plus attrayants.
-
/* Juste pour que notre exemple soit plus joli */
+```css
+/* Juste pour que notre exemple soit plus joli */
body {
font: 1em sans-serif;
padding: 0;
@@ -571,13 +499,15 @@ input:focus:invalid {
.error.active {
padding: 0.3em;
-}
+}
+```
-
JavaScript
+##### JavaScript
-
Le code JavaScript suivant gère la validation personnalisée des erreurs.
+Le code JavaScript suivant gère la validation personnalisée des erreurs.
-
// Il y a plusieurs façon de sélectionner un nœud DOM ; ici on récupère
+```js
+// Il y a plusieurs façon de sélectionner un nœud DOM ; ici on récupère
// le formulaire et le champ d'e-mail ainsi que l'élément span
// dans lequel on placera le message d'erreur
@@ -606,60 +536,61 @@ form.addEventListener("submit", function (event) {
// Et on empêche l'envoi des données du formulaire
event.preventDefault();
}
-}, false);
+L'API de validation des contraintes fournit un outil puissant pour gérer la validation des formulaires, en vous laissant un contrôle sur l'interface utilisateur bien supérieur à ce que vous auriez pu avoir avec uniquement HTML et CSS.
-
L'API de validation des contraintes fournit un outil puissant pour gérer la validation des formulaires, en vous laissant un contrôle sur l'interface utilisateur bien supérieur à ce que vous auriez pu avoir avec uniquement HTML et CSS.
+### Valider des formulaires sans API intégrée
-
Valider des formulaires sans API intégrée
+Il arrive parfois, comme c'est le cas avec des navigateurs anciens ou de [widgets personnalisés](/fr/docs/HTML/Forms/How_to_build_custom_form_widgets), de ne pas pouvoir (ou vouloir) utiliser l'API de validation des contraintes. Dans ce cas, vous pourrez toujours utiliser JavaScript pour valider votre formulaire. Valider un formulaire est plus une question d'interface utilisateur que de réelle validation des données.
-
Il arrive parfois, comme c'est le cas avec des navigateurs anciens ou de widgets personnalisés, de ne pas pouvoir (ou vouloir) utiliser l'API de validation des contraintes. Dans ce cas, vous pourrez toujours utiliser JavaScript pour valider votre formulaire. Valider un formulaire est plus une question d'interface utilisateur que de réelle validation des données.
+Pour valider un formulaire, vous devez vous poser un certain nombre de questions:
-
Pour valider un formulaire, vous devez vous poser un certain nombre de questions:
+- Quel type de validation dois-je réaliser ?
+ - : Vous devez déterminer comment valider vos données : opération sur des chaînes de caractères, conversion de type, expressions rationnelles, etc. C'est comme vous voulez. Mais retenez simplement que les données de formulaire sont toujours du texte et sont toujours fournies à vos scripts sous forme de chaînes de caractères.
+- Que dois-je faire si le formulaire n'est pas valide ?
+ - : C'est clairement une affaire d'interface utilisateur. Vous devez décider comment le formulaire doit se comporter : enverra-t-il quand même les données ? Devriez-vous mettre en évidence les champs qui sont en erreur ? Devriez-vous afficher des messages d'erreur ?
+- Comment puis-je aider l'utilisateur à corriger ses données invalides?
-
-
Quel type de validation dois-je réaliser ?
-
Vous devez déterminer comment valider vos données : opération sur des chaînes de caractères, conversion de type, expressions rationnelles, etc. C'est comme vous voulez. Mais retenez simplement que les données de formulaire sont toujours du texte et sont toujours fournies à vos scripts sous forme de chaînes de caractères.
-
Que dois-je faire si le formulaire n'est pas valide ?
-
C'est clairement une affaire d'interface utilisateur. Vous devez décider comment le formulaire doit se comporter : enverra-t-il quand même les données ? Devriez-vous mettre en évidence les champs qui sont en erreur ? Devriez-vous afficher des messages d'erreur ?
-
Comment puis-je aider l'utilisateur à corriger ses données invalides?
-
Pour limiter la frustration de l'utilisateur, il est très important de fournir autant d'information d'aide que nécessaire pour le guider dans la correction de sa saisie. Vous devriez afficher des suggestions en amont pour que l'utilisateur sache ce qui est attendu, ainsi que des messages d'erreur clairs. Si vous souhaitez vous plonger dans les exigences d'interface utilsateur pour la validation de formulaires, voici quelques articles (en anglais) utiles que vous devriez lire :
+ - : Pour limiter la frustration de l'utilisateur, il est très important de fournir autant d'information d'aide que nécessaire pour le guider dans la correction de sa saisie. Vous devriez afficher des suggestions en amont pour que l'utilisateur sache ce qui est attendu, ainsi que des messages d'erreur clairs. Si vous souhaitez vous plonger dans les exigences d'interface utilsateur pour la validation de formulaires, voici quelques articles (en anglais) utiles que vous devriez lire :
-
Exemple sans utilisation de la validation des contraintes
+ - SmashingMagazine : [Form-Field Validation: The Errors-Only Approach](http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/)
+ - SmashingMagazine : [Web Form Validation: Best Practices and Tutorials](http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/)
+ - Six Revision : [Best Practices for Hints and Validation in Web Forms](http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/)
+ - A List Apart : [Inline Validation in Web Forms](https://www.alistapart.com/articles/inline-validation-in-web-forms/)
-
Afin d'illustrer le propos, réécrivons le précédent exemple afin qu'il fonctionne avec d'anciens navigateurs:
+#### Exemple sans utilisation de la validation des contraintes
-
<form>
- <p>
- <label for="mail">
- <span>Veuillez saisir une adresse e-mail :</span>
- <input type="text" class="mail" id="mail" name="mail">
- <span class="error" aria-live="polite"></span>
- </label>
- <p>
- <!-- Certains navigateurs historiques ont besoin de l'attribut
- `type` avec la valeur `submit` sur l'élément `button` -->
- <button type="submit">Envoyer</button>
-</form>
+Afin d'illustrer le propos, réécrivons le précédent exemple afin qu'il fonctionne avec d'anciens navigateurs:
-
Comme vous pouvez voir, le HTML est quasiment identique; nous avons juste enlevé les fonctionnalités de validation HTML. Notez que ARIA est une spécification indépendante qui n'est pas spécifiquement liée à HTML5.
+```html
+
+```
-
CSS
+Comme vous pouvez voir, le HTML est quasiment identique; nous avons juste enlevé les fonctionnalités de validation HTML. Notez que [ARIA](/fr/docs/Accessibility/ARIA "/en-US/docs/Accessibility/ARIA") est une spécification indépendante qui n'est pas spécifiquement liée à HTML5.
-
De même, nous n'avons pas eu à changer radicalement les CSS ; nous avons simplement transformé la pseudo-classe {{cssxref(":invalid")}} en une vraie classe et évité d'utiliser le sélecteur d'attribut, qui ne fonctionne pas avec Internet Explorer 6.
+##### CSS
-
/* On améliore l'aspect de l'exemple avec ces quelques règles */
+De même, nous n'avons pas eu à changer radicalement les CSS ; nous avons simplement transformé la pseudo-classe {{cssxref(":invalid")}} en une vraie classe et évité d'utiliser le sélecteur d'attribut, qui ne fonctionne pas avec Internet Explorer 6.
+
+```css
+/* On améliore l'aspect de l'exemple avec ces quelques règles */
body {
font: 1em sans-serif;
padding: 0;
@@ -714,13 +645,15 @@ input:focus.invalid {
.error.active {
padding: 0.3em;
-}
+}
+```
-
JavaScript
+##### JavaScript
-
Les changements les plus importants sont dans le code JavaScript, qui nécessite bien plus que de simples retouches.
+Les changements les plus importants sont dans le code JavaScript, qui nécessite bien plus que de simples retouches.
-
// Il existe moins de méthode pour sélectionner un nœud DOM
+```js
+// Il existe moins de méthode pour sélectionner un nœud DOM
// avec les navigateurs historiques
var form = document.getElementsByTagName('form')[0];
var email = document.getElementById('mail');
@@ -732,7 +665,7 @@ var error = email;
while ((error = error.nextSibling).nodeType != 1);
// Pour respecter la spécification HTML5
-var emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
+var emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/;
// De nombreux navigateurs historiques ne supportent pas la méthode
// addEventListener. Voici une méthode simple (il en existe d'autres)
@@ -795,62 +728,52 @@ addEvent(form, "submit", function () {
error.innerHTML = "";
error.className = "error";
}
-});
+});
+```
+
+Voici le résultat:
+
+{{EmbedLiveSample("Exemple_sans_utilisation_de_la_validation_des_contraintes", "100%", 130)}}
+
+Comme vous avez pu le voir, il n'est pas si difficile de créer par soi-même un système de validation. La difficulté consiste à rendre le tout assez générique pour l'utiliser à la fois sur toutes les plateformes et pour chaque formulaire que vous pourriez créer. Il existe de nombreuses bibliothèques permettant ce genre de validation de formulaire ; n'hésitez pas à les utiliser. En voici quelques exemples :
-
Comme vous avez pu le voir, il n'est pas si difficile de créer par soi-même un système de validation. La difficulté consiste à rendre le tout assez générique pour l'utiliser à la fois sur toutes les plateformes et pour chaque formulaire que vous pourriez créer. Il existe de nombreuses bibliothèques permettant ce genre de validation de formulaire ; n'hésitez pas à les utiliser. En voici quelques exemples :
Il peut être utile, dans certains cas, d'effectuer une validation à distance. Ce genre de validation est nécessaire lorsque les données saisies par l'utilisateur sont liées à des données supplémentaires stockées sur le serveur hébergeant votre application. Prenons par exemple les formulaires d'inscription, pour lesquels on vous demande un nom d'utilisateur. Pour éviter toute duplication d'un nom d'utilisateur, il est plus judicieux d'effectuer une requête AJAX pour vérifier la disponibilté du nom d'utilisateur que de demander à envoyer les données saisies et de renvoyer le formulaire avec une erreur.
+Il peut être utile, dans certains cas, d'effectuer une validation à distance. Ce genre de validation est nécessaire lorsque les données saisies par l'utilisateur sont liées à des données supplémentaires stockées sur le serveur hébergeant votre application. Prenons par exemple les formulaires d'inscription, pour lesquels on vous demande un nom d'utilisateur. Pour éviter toute duplication d'un nom d'utilisateur, il est plus judicieux d'effectuer une requête AJAX pour vérifier la disponibilté du nom d'utilisateur que de demander à envoyer les données saisies et de renvoyer le formulaire avec une erreur.
-
Pour réaliser une telle validation, plusieurs précautions doivent être prises :
+Pour réaliser une telle validation, plusieurs précautions doivent être prises :
-
-
Il est nécessaire d'exposer une API et des données ; assurez-vous que ces données ne soient pas critiques.
-
Un décalage (lag) du réseau nécessite une validtion asynchrone. L'interface utilisateur doit être conçue de façon à pas être bloquée si cette validation n'est pas réalisée correctement.
-
+- Il est nécessaire d'exposer une API et des données ; assurez-vous que ces données ne soient pas critiques.
+- Un décalage (_lag_) du réseau nécessite une validtion asynchrone. L'interface utilisateur doit être conçue de façon à pas être bloquée si cette validation n'est pas réalisée correctement.
-
Conclusion
+## Conclusion
-
La validation d'un formulaire ne requiert pas de code JavaScript complexe, mais il est nécessaire de penser tout particulièrement à l'utilisateur. Rappelez-vous de toujours aider l'utilisateur à corriger les données qu'il saisit. Pour ce faire, assurez-vous de toujours :
+La validation d'un formulaire ne requiert pas de code JavaScript complexe, mais il est nécessaire de penser tout particulièrement à l'utilisateur. Rappelez-vous de toujours aider l'utilisateur à corriger les données qu'il saisit. Pour ce faire, assurez-vous de toujours :
-
-
Afficher des messages d'erreur explicites.
-
Être tolérant sur le format des données à envoyer.
-
Indiquer exactement où est l'erreur (en particulier pour les formulaires longs).
-
+- Afficher des messages d'erreur explicites.
+- Être tolérant sur le format des données à envoyer.
+- Indiquer exactement où est l'erreur (en particulier pour les formulaires longs).
-
+- [Mon premier formulaire HTML](/fr/docs/Learn/Forms/Your_first_form)
+- [Comment structurer un formulaire HTML](/fr/docs/Learn/Forms/How_to_structure_a_web_form)
+- [Les widgets natifs pour formulaire](/fr/docs/Learn/Forms/Basic_native_form_controls)
+- [Envoi des données de formulaire](/fr/docs/Learn/Forms/Sending_and_retrieving_form_data)
+- [Validation des données de formulaire](/fr/docs/Learn/Forms/Form_validation)
+- [Comment construire des widgets personnalisés pour formulaire](/fr/docs/Learn/Forms/How_to_build_custom_form_controls)
+- [Envoi de formulaires à l'aide du JavaScript](/fr/docs/Learn/Forms/Sending_forms_through_JavaScript)
+- [Formulaires HTML dans les navigateurs anciens](/fr/docs/Learn/Forms/HTML_forms_in_legacy_browsers)
+- [Mise en forme des formulaires HTML](/fr/docs/Learn/Forms/Styling_web_forms)
+- [Mise en forme avancée des formulaires HTML](/fr/docs/Learn/Forms/Advanced_form_styling)
+- [Table de compatibilité des propriétés pour les widgets de formulaire](/fr/docs/Learn/Forms/Property_compatibility_table_for_form_controls)
diff --git a/files/fr/learn/forms/how_to_build_custom_form_controls/example_1/index.md b/files/fr/learn/forms/how_to_build_custom_form_controls/example_1/index.md
index 20e96ebc26..2cc868993f 100644
--- a/files/fr/learn/forms/how_to_build_custom_form_controls/example_1/index.md
+++ b/files/fr/learn/forms/how_to_build_custom_form_controls/example_1/index.md
@@ -9,26 +9,29 @@ translation_of: Learn/Forms/How_to_build_custom_form_controls/Example_1
original_slug: >-
Web/Guide/HTML/Formulaires/Comment_construire_des_widgets_de_formulaires_personnalisés/Exemple_1
---
-
+C'est le premier exemple de code qui explique [comment construire un widget de formulaire personnalisé](/fr/docs/Web/Guide/HTML/Forms/How_to_build_custom_form_widgets).
-
.widget select,
+Ceci est le deuxième exemple expliquant comment [construire un formulaire personnalisé](/fr/docs/HTML/Forms/How_to_build_custom_form_widgets "/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets").
+
+## JS
+
+### HTML Content
+
+```html
+
.widget select,
+Ceci est le quatrième exemple expliquant [comment construire des widgets de formulaire personnalisés](/fr/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets).
+
+## Changement d'état
+
+### Contenu HTML
+
+```html
+
.widget select,
+Voici le dernier exemple expliquant [comment construire des widgets de formulaire personnalisés](/fr/docs/HTML/Forms/How_to_build_custom_form_widgets "/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets").
+
+## Changement d'état
+
+### Contenu HTML
+
+```html
+
Dans de nombreux cas les widgets de formulaires HTML disponibles ne suffisent pas. Si vous voulez composer certains widgets dans un style avancé tels que l'élément {{HTMLElement("select")}} ou si vous voulez leur donner des comportements personnalisés, vous n'avez pas d'autre choix que de créer vos propres widgets.
+Dans de nombreux cas les [widgets de formulaires HTML disponibles](/fr/docs/Web/Guide/HTML/Formulaires/Les_blocs_de_formulaires_natifs) ne suffisent pas. Si vous voulez composer certains widgets dans un [style avancé](/fr/docs/Web/Guide/HTML/Formulaires/Advanced_styling_for_HTML_forms) tels que l'élément {{HTMLElement("select")}} ou si vous voulez leur donner des comportements personnalisés, vous n'avez pas d'autre choix que de créer vos propres widgets.
-
Dans cet article, nous verrons comment construire un tel widget. Pour cela, nous allons travailler avec un exemple : reconstruire l'élément {{HTMLElement("select")}}.
+Dans cet article, nous verrons comment construire un tel widget. Pour cela, nous allons travailler avec un exemple : reconstruire l'élément {{HTMLElement("select")}}.
-
-
Note : Nous nous resterons centrés sur la construction des widgets, et non sur la façon de rendre le code générique et réutilisable ; cela impliquerait une manipulation de code JavaScript et de DOM dans un contexte inconnu, et nous sortirions de la portée de cet article.
-
+> **Note :** Nous nous resterons centrés sur la construction des widgets, et non sur la façon de rendre le code générique et réutilisable ; cela impliquerait une manipulation de code JavaScript et de DOM dans un contexte inconnu, et nous sortirions de la portée de cet article.
-
Conception, structure et sémantique
+## Conception, structure et sémantique
-
Avant de créer un widget personnalisé, il faut commencer par déterminer exactement ce que vous voulez. Vous gagnerez ainsi un temps précieux. En particulier, il est important de définir clairement tous les états de votre widget. Pour ce faire, il est bon de commencer par un widget existant dont les états et le comportement sont bien connus, afin que vous puissiez simplement les imiter autant que possible.
+Avant de créer un widget personnalisé, il faut commencer par déterminer exactement ce que vous voulez. Vous gagnerez ainsi un temps précieux. En particulier, il est important de définir clairement tous les états de votre widget. Pour ce faire, il est bon de commencer par un widget existant dont les états et le comportement sont bien connus, afin que vous puissiez simplement les imiter autant que possible.
-
Dans notre exemple, nous allons reconstruire l'élément {{HTMLElement("select")}}}. Voici le résultat que nous voulons atteindre :
+Dans notre exemple, nous allons reconstruire l'élément {{HTMLElement("select")}}}. Voici le résultat que nous voulons atteindre :
-
+
-
Cette capture d'écran montre les trois états principaux du widget : l'état normal (à gauche), l'état actif (au milieu) et l'état ouvert (à droite).
+Cette capture d'écran montre les trois états principaux du widget : l'état normal (à gauche), l'état actif (au milieu) et l'état ouvert (à droite).
-
En termes de comportement, nous voulons que notre widget soit utilisable aussi bien avec une souris qu'avec un clavier, comme n'importe quel widget natif. Commençons par définir comment le widget atteint chaque état :
+En termes de comportement, nous voulons que notre widget soit utilisable aussi bien avec une souris qu'avec un clavier, comme n'importe quel widget natif. Commençons par définir comment le widget atteint chaque état :
-
Le widget est dans son état normal :
+Le widget est dans son état normal :
-
-
la page se charge
-
le widget était actif et l'utilisateur a cliqué quelque part en dehors du widget
-
le widget était actif et l'utilisateur a déplacé le focus sur un autre avec le clavier
-
+- la page se charge
+- le widget était actif et l'utilisateur a cliqué quelque part en dehors du widget
+- le widget était actif et l'utilisateur a déplacé le focus sur un autre avec le clavier
-
-
Note : Déplacer le focus dans la page entre les divers widgets se fait généralement en appuyant sur la touche de tabulation, mais ce n'est pas la norme partout. Par exemple, circuler parmi les liens sur une page se fait dans Safari par défaut en utilisant la combinaison Option+Tab.
-
+> **Note :** Déplacer le focus dans la page entre les divers widgets se fait généralement en appuyant sur la touche de tabulation, mais ce n'est pas la norme partout. Par exemple, circuler parmi les liens sur une page se fait dans Safari par défaut en utilisant la [combinaison Option+Tab](http://www.456bereastreet.com/archive/200906/enabling_keyboard_navigation_in_mac_os_x_web_browsers/).
-
Le widget est sans son état actif :
-
-
-
l'utilisateur clique sur lui
-
l'utilisateur presse la touche Tabulation et obtient le focus
-
le widget était dans l'état ouvert et l'utilisateur a cliqué dessus.
-
-
-
Le widget est dans un état ouvert :
-
-
-
le widget est dans un état autre que ouvert et l'utilisateur clique dessus.
-
+Le widget est sans son état actif :
-
Maintenant que nous savons comment changer les états du widget, il est important de définir comment changer la valeur du widget :
+- l'utilisateur clique sur lui
+- l'utilisateur presse la touche Tabulation et obtient le focus
+- le widget était dans l'état ouvert et l'utilisateur a cliqué dessus.
-
La valeur change quand :
+Le widget est dans un état ouvert :
-
-
l'utilisateur clique sur une option quand le widget est dans l'état ouvert
-
l'utilisateur presse la touche ↑ ou ↓ quand le widget est dans l'état actif
-
+- le widget est dans un état autre que ouvert et l'utilisateur clique dessus.
-
Enfin, définissons comment les options du widget doivent se comporter :
+Maintenant que nous savons comment changer les états du widget, il est important de définir comment changer la valeur du widget :
-
-
Quand le widget est ouvert, l'option sélectionnée est mise en valeur
-
Quand la souris est sur une option, l'option est mise en valeur et l'option précédemment mise en valeur revient à l'état normal
-
+La valeur change quand :
-
Pour les besoins de notre exemple, nous nous arrêterons là ; cependant, si vous êtes un lecteur attentif, vous remarquerez que certains comportements ne sont pas précisés. Par exemple, que pensez-vous qu'il se passe si l'utilisateur appuie sur la touche Tabulation alors que le widget est dans l'état ouvert ? La réponse est… rien. D'accord, le bon comportement semble évident mais le fait est que, comme il n'est pas défini dans nos spécifications, il est très facile de fermer les yeux sur ce comportement. Dans un travail collaboratif, lorsque les personnes concevant le comportement du widget sont différentes de celles qui le mettent en œuvre, cette démarche se vérifiera.
+- l'utilisateur clique sur une option quand le widget est dans l'état ouvert
+- l'utilisateur presse la touche
-
Autre exemple amusant : que se passera-t-il si l'utilisateur presse les touches ↑ ou ↓ alors que le widget est à l'état ouvert ? Ici, c'est un peu plus délicat. Si vous considérez que l'état actif et l'état ouvert sont totalement différents, la réponse est encore une fois « rien ne se produira » parce que nous n'avons pas défini d'interactions clavier pour l'état ouvert. D'autre part, si vous considérez que l'état actif et l'état ouvert coïncident, la valeur peut changer mais l'option ne sera certainement pas mise en valeur en conséquence, encore une fois parce que nous n'avons pas défini d'interactions clavier sur les options lorsque le widget est dans son état ouvert (nous avons seulement défini ce qui doit se passer lorsque le widget est ouvert, mais rien après).
+ ↑
-
Dans notre exemple, les spécifications manquantes sont évidentes et nous les traiterons, mais cela peut devenir un problème réel sur de nouveaux widgets exotiques, pour lesquels personne n'a la moindre idée de ce qu'est le bon comportement. Il est donc toujours bon de passer du temps à l'étape conception, car si vous définissez pauvrement le comportement, ou si vous oubliez de le définir, il sera très difficile de le redéfinir une fois les utilisateurs habitués. Si vous avez des doutes, demandez l'avis des autres, et si vous avez le budget pour cela, n'hésitez pas à faire des tests utilisateur. Ce processus est appelé UX Design (User eXperience). Si vous voulez en savoir plus sur ce sujet, vous devriez consulter les ressources utiles suivantes :
Note : De plus, dans la plupart des systèmes, il y a moyen d'ouvrir l'élément {{HTMLElement("select")}} pour voir tous les choix disponibles (c'est la même chose que de cliquer sur l'élément {{HTMLElement("select")}} avec une souris). Cela se fait avec Alt+↓ sous Windows et n'a pas été implémenté dans notre exemple - mais il serait facile de le faire, car le mécanisme a déjà été implémenté pour l'événement click.
-
+ quand le widget est dans l'état actif
-
Definition de la structure HTML et de la sémantique
+Enfin, définissons comment les options du widget doivent se comporter :
-
Maintenant que la fonctionnalité de base du widget a été décidée, il est temps de commencer à construire notre widget. La première étape consiste à définir sa structure HTML et à lui donner une sémantique de base. Voici ce dont nous avons besoin pour reconstruire un élément <select> :
+- Quand le widget est ouvert, l'option sélectionnée est mise en valeur
+- Quand la souris est sur une option, l'option est mise en valeur et l'option précédemment mise en valeur revient à l'état normal
-
<!-- Ceci est notre conteneur principal pour le widget. L'attribut tabindex
- est ce qui permet à l'utilisateur de mettre le focus sur le widget.
- Nous verrons plus loin que c'est mieux de le faire avec JavaScript. -->
-<div class="select" tabindex="0">
+Pour les besoins de notre exemple, nous nous arrêterons là ; cependant, si vous êtes un lecteur attentif, vous remarquerez que certains comportements ne sont pas précisés. Par exemple, que pensez-vous qu'il se passe si l'utilisateur appuie sur la touche Tabulation alors que le widget est dans l'état ouvert ? La réponse est… rien. D'accord, le bon comportement semble évident mais le fait est que, comme il n'est pas défini dans nos spécifications, il est très facile de fermer les yeux sur ce comportement. Dans un travail collaboratif, lorsque les personnes concevant le comportement du widget sont différentes de celles qui le mettent en œuvre, cette démarche se vérifiera.
+
+Autre exemple amusant : que se passera-t-il si l'utilisateur presse les touches ↑ ou ↓ alors que le widget est à l'état ouvert ? Ici, c'est un peu plus délicat. Si vous considérez que l'état actif et l'état ouvert sont totalement différents, la réponse est encore une fois « rien ne se produira » parce que nous n'avons pas défini d'interactions clavier pour l'état ouvert. D'autre part, si vous considérez que l'état actif et l'état ouvert coïncident, la valeur peut changer mais l'option ne sera certainement pas mise en valeur en conséquence, encore une fois parce que nous n'avons pas défini d'interactions clavier sur les options lorsque le widget est dans son état ouvert (nous avons seulement défini ce qui doit se passer lorsque le widget est ouvert, mais rien après).
+
+Dans notre exemple, les spécifications manquantes sont évidentes et nous les traiterons, mais cela peut devenir un problème réel sur de nouveaux widgets exotiques, pour lesquels personne n'a la moindre idée de ce qu'est le bon comportement. Il est donc toujours bon de passer du temps à l'étape conception, car si vous définissez pauvrement le comportement, ou si vous oubliez de le définir, il sera très difficile de le redéfinir une fois les utilisateurs habitués. Si vous avez des doutes, demandez l'avis des autres, et si vous avez le budget pour cela, n'hésitez pas à [faire des tests utilisateur](https://fr.wikipedia.org/wiki/Test_utilisateur). Ce processus est appelé UX Design (**U**ser e**X**perience). Si vous voulez en savoir plus sur ce sujet, vous devriez consulter les ressources utiles suivantes :
- <!-- Ce containeur sera utilisé pour afficher la valeur courante du widget -->
- <span class="value">Cerise</span>
+- [UXMatters.com](http://www.uxmatters.com/)
+- [UXDesign.com](http://uxdesign.com/)
+- [The UX Design section of SmashingMagazine](http://uxdesign.smashingmagazine.com/)
- <!-- Ce conteneur contiendra toutes les options disponibles pour le widget.
- Comme c'est une liste, il y sens à utiliser l'élément ul. -->
- <ul class="optList">
- <!-- Chaque option ne contient que la valeur à afficher, Nous verrons plus loin
- comment gérer la valeur réelle qui sera envoyée avec les données du formulaire -->
- <li class="option">Cerise</li>
- <li class="option">Citron</li>
- <li class="option">Banane</li>
- <li class="option">Fraise</li>
- <li class="option">Pomme</li>
- </ul>
+> **Note :** De plus, dans la plupart des systèmes, il y a moyen d'ouvrir l'élément {{HTMLElement("select")}} pour voir tous les choix disponibles (c'est la même chose que de cliquer sur l'élément {{HTMLElement("select")}} avec une souris). Cela se fait avec Alt+**↓** sous Windows et n'a pas été implémenté dans notre exemple - mais il serait facile de le faire, car le mécanisme a déjà été implémenté pour l'événement `click`.
-</div>
+### Definition de la structure HTML et de la sémantique
+
+Maintenant que la fonctionnalité de base du widget a été décidée, il est temps de commencer à construire notre widget. La première étape consiste à définir sa structure HTML et à lui donner une sémantique de base. Voici ce dont nous avons besoin pour reconstruire un élément \ :
+
+```html
+
+