<input type="month">
Limited availability
Cette fonctionnalité n'est pas Compatible car elle ne fonctionne pas dans certains des navigateurs les plus utilisés.
Les éléments <input> dont l'attribut type vaut month permettent de créer des contrôles où l'utilisateur·ice peut saisir un mois et année.
La valeur associée à un tel élément suit le format YYYY-MM, où YYYY représente l'année sur quatre chiffre et MM le mois sur deux chiffres.
Exemple interactif
<label for="start">Mois de début :</label>
<input type="month" id="start" name="start" min="2018-03" value="2018-05" />
label {
display: block;
font:
1rem "Fira Sans",
sans-serif;
}
input,
label {
margin: 0.4rem 0;
}
L'interface du contrôle varie généralement d'un navigateur à l'autre ; actuellement, la prise en charge est incomplète, seuls Chrome/Opera et Edge sur ordinateur — ainsi que la plupart des versions récentes de navigateurs mobiles — proposent des implémentations utilisables.
Dans les navigateurs qui ne prennent pas en charge les champs month, le contrôle revient à <input type="text">, bien qu'il puisse y avoir une validation automatique du texte saisi pour s'assurer qu'il est au format attendu.
Pour celles et ceux qui utilisent un navigateur ne prenant pas en charge month, la capture d'écran ci-dessous montre l'apparence du contrôle dans Chrome et Opera.
Un clic sur la flèche vers le bas à droite fait apparaître un sélecteur de date permettant de choisir le mois et l'année.

Voici un aperçu du contrôle sous Edge :

Valeur
Une chaîne de caractères représentant la valeur du mois et de l'année saisies dans le champ, au format YYYY-MM (année sur quatre chiffres ou plus, suivie d'un tiret (-), puis du mois sur deux chiffres).
Le format de la chaîne de mois utilisée par ce type de champ est décrit dans Représentation des mois.
Fournir une valeur par défaut
Vous pouvez définir une valeur par défaut pour le contrôle en incluant un mois et une année dans l'attribut value, comme ceci :
<label for="bday-month">Quel est le mois de votre naissance ?</label>
<input id="bday-month" type="month" name="bday-month" value="2017-06" />
À noter que le format de date affiché diffère de la véritable value ; la plupart des agents utilisateur affichent le mois et l'année dans un format adapté à la langue du système d'exploitation de l'utilisateur·ice, tandis que la date value est toujours formatée yyyy-MM.
Lorsque la valeur ci-dessus est envoyée au serveur, par exemple, elle aura la forme bday-month=1978-06.
Définir la valeur en JavaScript
Vous pouvez également obtenir et définir la valeur de la date en JavaScript à l'aide de la propriété HTMLInputElement.value, par exemple :
<label for="bday-month">Quel est le mois de votre naissance ?</label>
<input id="bday-month" type="month" name="bday-month" />
const monthControl = document.querySelector('input[type="month"]');
monthControl.value = "2001-06";
Attributs supplémentaires
En complément des attributs pris en charge par l'ensemble des éléments <input>, les champs pour les mois gèrent les attributs suivants.
list
La valeur de l'attribut list est l'id d'un élément <datalist> situé dans le même document.
L'élément <datalist> fournit une liste de valeurs prédéfinies à suggérer à l'utilisateur·ice pour ce champ.
Toute valeur de la liste qui n'est pas compatible avec le type n'est pas incluse dans les options suggérées.
Les valeurs fournies sont des suggestions et non des obligations : l'utilisateur·ice peut sélectionner une valeur de cette liste prédéfinie ou en fournir une différente.
max
L'année et le mois les plus tardifs, au format de chaîne de caractères décrit dans la section Valeur ci-dessus, à accepter.
Si la valeur saisie dans le champ (représentée par l'attribut value) est supérieure à cette date, la validation échouera.
Si la valeur de l'attribut max n'est pas une chaîne de caractères valide au format yyyy-MM, alors l'élément n'a pas de valeur maximale.
Cette valeur doit être supérieure ou égale à celle définie par l'attribut min.
min
Le mois le plus tôt, indiqué avec l'année, sous la forme d'une chaîne de caractères au format yyyy-MM.
Si la valeur saisie dans le champ (représentée par l'attribut value) est antérieure à cette date, la validation échouera.
Si une valeur est définie pour min qui n'est pas une chaîne de caractères valide pour une année et un mois, le champ n'a pas de valeur minimale.
Cette valeur doit être inférieure ou égale à celle définie par l'attribut max.
readonly
Un attribut booléen qui, s'il est présent, indique que ce champ ne peut pas être édité par l'utilisateur·ice.
Sa value peut cependant toujours être modifiée par du code JavaScript qui définit directement la valeur de la propriété HTMLInputElement.value.
Note :
Un champ en lecture seule pouvant ne pas avoir de valeur, l'attribut required n'aura aucun effet si l'attribut readonly est défini.
step
L'attribut step est un nombre qui définit la granularité à respecter pour la valeur, ou la valeur spéciale any (décrite ci-dessous). Seules les valeurs qui correspondent à un nombre entier de pas à partir de la base de pas sont valides. La base de pas est min si elle est définie, value sinon, ou 0 (l'époque Unix, 1970-01) si aucune n'est fournie.
Pour les champs de type month, la valeur de step est exprimée en mois. La valeur par défaut de step est 1, ce qui correspond à 1 mois.
Une chaîne de caractères any signifie qu'aucune contrainte de pas n'est appliquée et que n'importe quelle valeur est autorisée (sous réserve des autres contraintes, comme min et max). En réalité, cela a le même effet que 1 pour les champs month car l'interface de sélection ne permet de choisir que des mois entiers.
Note : Lorsque les données saisies par l'utilisateur·ice ne respectent pas la configuration du pas, l'agent utilisateur peut arrondir à la valeur valide la plus proche, en privilégiant les nombres dans le sens positif lorsque deux options sont aussi proches l'une de l'autre.
Utiliser les entrées de mois
Les champs liés aux dates (y compris month) semblent pratiques au premier abord ; ils promettent une interface simple pour choisir des dates et normalisent le format des données envoyées au serveur, quelle que soit la langue de l'utilisateur·ice.
Cependant, il existe des problèmes avec <input type="month"> car à ce jour, de nombreux navigateurs majeurs ne le prennent pas encore en charge.
Nous allons examiner des utilisations simples puis plus complexes de <input type="month">, puis donner des conseils pour pallier le problème de prise en charge des navigateurs dans la section Gérer la prise en charge des navigateurs.
Utilisation simple du mois
L'utilisation la plus simple de <input type="month"> consiste en une combinaison élémentaire d'un élément <input> et d'un élément <label>, comme illustré ci-dessous :
<form>
<label for="bday-month">Quel est le mois de votre naissance ?</label>
<input id="bday-month" type="month" name="bday-month" />
</form>
Indiquer une date maximale et une date minimale
On peut utiliser les attributs min et max afin de restreindre la période pendant laquelle l'utilisatrice ou l'utilisateur peut choisir un mois. Dans l'exemple qui suit, on définit une date au plus tôt avec 1900-01 et une date au plus tard avec 2017-08 :
<form>
<label for="bday-month">Quel est le mois de votre naissance ?</label>
<input
id="bday-month"
type="month"
name="bday-month"
min="1900-01"
max="2017-08" />
</form>
Grâce ce fragment de code :
- Seuls les mois entre janvier 1900 et août 2017 peuvent être sélectionnés (le contrôle ne doit pas permettre de sélectionner un mois en dehors de cette période) Selon le navigateur utilisé, vous pouvez constater que les mois en dehors de la période définie ne sont pas sélectionnables dans le sélecteur de mois (par exemple, Edge), ou non valides (voir Validation) mais restent disponibles (par exemple, Chrome).
Contrôler la taille du champ
<input type="month"> ne peut pas être dimensionné grâce à size, il vous faudra utiliser CSS si besoin.
Validation
Par défaut, <input type="month"> n'applique pas de validation particulière sur la valeur saisie. C'est l'interface utilisateur qui ne permet pas de choisir autre chose qu'un mois.
Les attributs min et max permettent de limiter la période valide et l'attribut required rend le champ obligatoire. Avec ces attributs, les navigateurs afficheront un message d'erreur si la date choisie est hors de la période ou si la valeur est vide.
Prenons un exemple avec une période délimitée et un champ obligatoire :
<form>
<div>
<label for="month">
À quel mois souhaitez-vous venir cet été (Juin à Sept.) ?
</label>
<input
id="month"
type="month"
name="month"
min="2022-06"
max="2022-09"
required />
<span class="validity"></span>
</div>
<div>
<input type="submit" value="Envoyer le formulaire" />
</div>
</form>
Si vous tentez d'envoyer le formulaire avec une date incomplète ou en dehors de cette période, le navigateur doit afficher un message d'erreur. Voici le résultat en direct :
Voici une capture d'écran qui illustre le résultat obtenu avec un navigateur prenant en charge cette fonctionnalité :

Voici ensuite la feuille de style CSS utilisée dans l'exemple précédent.
On utilise :valid et :invalid afin de mettre en forme le contrôle selon que la valeur saisie est invalide.
Les icônes ajoutées sont placées dans un élément <span> à part car Chrome ne permet pas de gérer du contenu généré à même le contrôle ni de mettre en forme ce contenu généré.
div {
margin-bottom: 10px;
position: relative;
}
input[type="number"] {
width: 100px;
}
input + span {
padding-right: 30px;
}
input:invalid + span::after {
position: absolute;
content: "✖";
padding-left: 5px;
}
input:valid + span::after {
position: absolute;
content: "✓";
padding-left: 5px;
}
Attention : La validation des formulaires HTML n'est pas un substitut aux scripts qui garantissent que les données saisies sont dans le bon format. Il est bien trop facile pour quelqu'un de modifier le HTML afin de contourner la validation, ou de la supprimer entièrement. Il est aussi possible pour une personne de contourner totalement votre HTML et d'envoyer les données directement à votre serveur. Si votre code côté serveur ne valide pas les données qu'il reçoit, une catastrophe peut survenir lorsque des données mal formatées sont envoyées (ou des données trop volumineuses, d'un type incorrect, et ainsi de suite).
Gérer la prise en charge des navigateurs
Comme évoqué plus haut, le problème principal relatif à ces contrôles est l'absence partielle de prise en charge des navigateurs. Seuls Chrome, Opera et Edge supportent ce type de contrôle sur ordinateurs et la plupart des navigateurs mobiles le prennent en charge.
À titre d'exemple, le sélecteur month sur Chrome pour Android ressemble à ceci :

Les navigateurs ne prenant pas en charge basculent gracieusement vers un champ de type texte, mais cela pose des problèmes à la fois en termes de cohérence de l'interface utilisateur (le contrôle présenté sera différent), et de gestion des données.
Le second problème est le plus grave des deux.
Comme indiqué plus haut, pour un champ month la valeur réelle est toujours normalisée au format yyyy-mm.
En revanche, dans sa configuration par défaut, un champ text n'a aucune idée du format que doit avoir la date, ce qui pose problème en raison du nombre de façons différentes dont les personnes écrivent les dates.
Par exemple :
mmyyyy(072022)mm/yyyy(07/2022)mm-yyyy(07-2022)yyyy-mm(2022-07)Month yyyy(Juillet 2022)- …et ainsi de suite.
Une façon de contourner ce problème consiste à ajouter un attribut pattern sur votre champ month.
Bien que le champ month ne l'utilise pas, si le navigateur revient à le traiter comme un champ text, le motif sera utilisé.
Par exemple, essayez d'afficher la démonstration suivante dans un navigateur qui ne prend pas en charge les champs month :
<form>
<div>
<label for="month">
À quel mois souhaitez-vous venir cet été (Juin à Sept.) ?
</label>
<input
id="month"
type="month"
name="month"
min="2022-06"
max="2022-09"
required
pattern="[0-9]{4}-[0-9]{2}" />
<span class="validity"></span>
</div>
<div>
<input type="submit" value="Envoyer le formulaire" />
</div>
</form>
Si vous tentez de l'envoyer, vous verrez que le navigateur affiche désormais un message d'erreur (et indique que le champ est invalide) si votre saisie ne correspond pas au motif nnnn-nn, où n est un chiffre entre 0 et 9.
Bien entendu, cela n'empêche pas les personnes de saisir des dates invalides (comme 0000-42) ou des dates mal formatées qui respectent le motif.
Il y a aussi le problème que l'utilisateur·ice ne saura pas nécessairement quel format de date est attendu. Il reste du travail à faire.
La meilleure façon de gérer la saisie de dates dans les formulaires de manière compatible entre navigateurs (tant que tous les navigateurs majeurs ne les prennent pas en charge) est de demander à l'utilisateur·ice de saisir le mois et l'année dans deux contrôles séparés (les éléments <select> sont populaires ; voir plus bas pour une implémentation), ou d'utiliser des bibliothèques JavaScript comme le plugin sélecteur de date jQuery (angl.).
Exemples
Dans cet exemple, nous créons deux ensembles d'éléments d'interface, chacun permettant à l'utilisateur·ice de sélectionner un mois et une année.
Le premier est un champ natif de type month, et l'autre est une paire d'éléments <select> qui permettent de choisir le mois et l'année séparément, pour assurer la compatibilité avec les navigateurs qui ne prennent pas encore en charge <input type="month">.
HTML
Voici le fragment de code HTML utilisé :
<form>
<div class="nativeDatePicker">
<label for="month-visit">
À quel mois souhaitez-vous venir cet été ?
</label>
<input type="month" id="month-visit" name="month-visit" />
<span class="validity"></span>
</div>
<p class="fallbackLabel">À quel mois souhaitez-vous venir cet été ?</p>
<div class="fallbackDatePicker">
<div>
<span>
<label for="month">Mois :</label>
<select id="month" name="month">
<option selected>Janvier</option>
<option>Février</option>
<option>Mars</option>
<option>Avril</option>
<option>Mai</option>
<option>Juin</option>
<option>Juillet</option>
<option>Août</option>
<option>Septembre</option>
<option>Octobre</option>
<option>Novembre</option>
<option>Décembre</option>
</select>
</span>
<span>
<label for="year">Année :</label>
<select id="year" name="year"></select>
</span>
</div>
</div>
</form>
Le <div> avec l'identifiant nativeDatePicker utilise le type de champ month pour demander le mois et l'année, tandis que le <div> avec l'identifiant fallbackDatePicker utilise une paire d'éléments <select>.
Le premier demande le mois, et le second l'année.
Le <select> pour choisir le mois est codé en dur avec les noms des mois, car ils ne changent pas (la localisation n'est pas prise en compte ici).
La liste des années disponibles est générée dynamiquement en fonction de l'année courante (voir les commentaires du code ci-dessous pour des explications détaillées sur le fonctionnement de ces fonctions).
JavaScript
Le code JavaScript qui gère le choix de la méthode à utiliser et qui prépare la liste des années à inclure dans le <select> non natif suit.
La partie la plus intéressante de l'exemple est le code de détection de fonctionnalité.
Pour détecter si le navigateur prend en charge <input type="month">, on crée un nouvel élément <input>, on essaie de définir son type à month, puis on vérifie immédiatement la valeur de son type.
Les navigateurs qui ne prennent pas en charge le type month retourneront text, car c'est la valeur de repli lorsque month n'est pas pris en charge.
Si <input type="month"> n'est pas pris en charge, on masque le sélecteur natif et on affiche l'interface de sélection alternative.
// On définit des variables
const nativePicker = document.querySelector(".nativeDatePicker");
const fallbackPicker = document.querySelector(".fallbackDatePicker");
const fallbackLabel = document.querySelector(".fallbackLabel");
const yearSelect = document.querySelector("#year");
const monthSelect = document.querySelector("#month");
// Par défaut on masque le sélecteur alternatif
fallbackPicker.style.display = "none";
fallbackLabel.style.display = "none";
// On teste si un nouveau contrôle est automatiquement
// converti en un champ texte
const test = document.createElement("input");
try {
test.type = "month";
} catch (e) {
console.log(e.description);
}
// Si c'est le cas, on exécute le code dans ce bloc if
if (test.type === "text") {
// on masque le sélecteur natif et on masque le sélecteur alternatif
nativePicker.style.display = "none";
fallbackPicker.style.display = "block";
fallbackLabel.style.display = "block";
// on génère les valeurs pour les années
populateYears();
}
function populateYears() {
// On récupère l'année courante
const date = new Date();
const year = date.getFullYear();
// On ajoute l'année courante et les 100 années à venir
// dans l'élément <select> pour l'année
for (let i = 0; i <= 100; i++) {
const option = document.createElement("option");
option.textContent = year - i;
yearSelect.appendChild(option);
}
}
Note : Attention, certaines années peuvent contenir 53 semaines ! (cf. cet article Wikipédia (angl.)) Il vous faudra prendre cela en compte si vous souhaitez développer des applications réelles.
Résumé technique
| Valeur | Une chaîne de caractères représentant un mois et une année, ou bien la chaîne vide. |
| Évènements |
change et
input
|
| Attributs communs pris en charge |
autocomplete,
list,
readonly,
step
|
| Attributs IDL |
list,
value,
valueAsDate,
valueAsNumber
|
| Interface DOM | HTMLInputElement |
| Méthodes |
select(),
stepDown(),
stepUp().
|
| Rôle ARIA implicite | Pas de rôle correspondant (angl.) |
Spécifications
| Specification |
|---|
| HTML> # month-state-(type=month)> |
Compatibilité des navigateurs
Voir aussi
- L'élément générique
<input>et l'interface DOMHTMLInputElementqui permet de le manipuler - Les formats de date et d'heure utilisés en HTML
- Un tutoriel à propos des sélecteurs de dates et d'heures
- Les éléments
<input type="datetime-local">,<input type="date">,<input type="time">et<input type="week">