Les éléments <input> dont l'attribut type vaut time permettent de créer des contrôles où l'utilisateur peut saisir une heure.

L'interface utilisateur affichée pour le contrôle peut varier d'un navigateur à l'autre. À l'heure où nous écrivons ces lignes, seul Safari ne prend pas en charge ce type de contrôle. Pour ce dernier, l'élément sera transformé en simple <input type="text">.

<input id="time" type="time">

Pour Chrome/Opera, le contrôle time possède deux cases permettant de saisir les heures d'une part et les minutes d'autre part (sur 24 heures), deux flèches pour augmenter ou réduire la valeur et une croix permettant de supprimer la valeur.

Pour Firefox, l'aspect du contrôle est similaire mais il ne possède pas les flèches d'incrément et l'horloge est une horloge sur 12 heures, une troisième case permettant de choisir le matin (AM) ou l'après-midi (PM).

Pour Edge, le contrôle affiché est un plus élaboré : il affiche un sélecteur avec deux bandes déroulantes pour choisir l'heure et les minutes (là aussi, l'horloge est sur 24 heures) :

Valeur Une chaîne de caractères (DOMString) qui représente un heure (avec des minutes) ou bien une chaîne de caractères vide.
Évènements change et input.
Attributs pris en charge autocomplete, list, readonly et step.
Attributs IDL value, valueAsDate, valueAsNumber, list.
Méthodes select(), stepDown(), stepUp().

Valeur

Une chaîne de caractères (DOMString) qui représente la valeur de l'heure saisie dans le contrôle. Il est possible de définir une valeur par défaut en indiquant une heure dans l'attribut value :

<label for="appt-time">Veuillez choisir une heure de rendez-vous :</label>
<input id="appt-time" type="time" name="appt-time" value="13:30">

Attention, le format d'affichage peut être différent de la valeur exacte contenue dans l'attribut value. Le format d'affichage sera choisi en fonction de la locale du système d'exploitation de l'utilisateur alors que la valeur de value suivra toujours le format hh:mm (où hh représente les deux chiffres de l'heure sur 24 heures et où mm représente les deux chiffres pour les minutes). Ainsi, 13:30, pourra être affiché sous la forme 1.30 PM dans le contrôle mais la valeur envoyée avec le formulaire sera toujours appt-time=13%3A30.

Il est également possible d'obtenir et de fixer l'heure en JavaScript grâce à la propriété HTMLInputElement.value. Par exemple :

var timeControl = document.querySelector('input[type="time"]');
timeControl.value = '15:30';

Utiliser <input type="time">

Ces champs de saisie peuvent sembler pratiques : ils fournissent simplement une interface utilisateur pour sélectionner ds heures et normalisent les données dans un format (indépendant de la locale de l'utilisateur) avant de l'envoyer au serveur. Toutefois, quelques écueils peuvent apparaître en raison de la prise en charge hétérogène des différents navigateurs.

Dans la suite de cet article, nous verrons des cas d'utilisation simples puis complexes autour de <input type="time"> puis nous verrons comment gérer l'absence de prise en charge des navigateur avec un exemple plus développé.

Utilisation simple

Dans sa forme la plus simple, <input type="time"> n'est accompagné que d'un élément <label> :

<form>
  <label for="appt-time">Veuillez choisir une heure de rendez-vous : </label>
  <input id="appt-time" type="time" name="appt-time">
</form>

Ajuster la taille du contrôle

<input type="time"> ne prend pas en charge d'attribut qui permette de le dimensionner (à la façon de size). Il faut donc utiliser CSS si besoin.

Utiliser l'attribut step

L'attribut step peut être utilisé afin de faire varier l'incrément de temps lorsqu'on passe d'une valeur à la suivante ou à la précédente. Attention toutefois, cela n'est pas pris en charge ou homogène parmi les différents navigateurs.

La valeur de cet attribut est un entier exprimant le nombre de secondes à incrémenter. Si on choisit une valeur inférieure à 60 secondes (c'est-à-dire 1 minute), le contrôle time affichera alors une troisième section pour les secondes après les heures et les minutes:

<form>
  <label for="appt-time">Veuillez choisir une heure de rendez-vous : </label>
  <input id="appt-time" type="time" name="appt-time" step="2">
</form>

Cependant, cela ne semble avoir un effet prévisible que pour Chrome/Opera qui sont les deux navigateurs à posséder des flèches d'incrément. Avant l'exemple précédent, cliquer sur le flèche augmentera/réduira l'heure de deux secondes (si on souhaite manipuler des minutes, il faudra multiplier par 60 et de même pour les heures : un incrément de 120 correspondra à 2 minutes et un incrément de 7200 correspondra à 2 heures).

Cet attribut semble n'avoir aucun impact pour Firefox ou Edge voire empêche la validation de fonctionner (voir la prochaine section).

Validation

Par défaut <input type="time"> ne valide pas les valeurs saisies. En effet, l'interface utilisateur ne permet de choisir une valeur exotique (par exemple 36:87).

Indiquer une heure maximale et minimale

Les attributs min et max permettent de réduire la plage horaire valide pendant laquelle l'utilisateur peut sélectionner une heure. Dans l'exemple suivant, l'utilisateur peut saisir une heure minimum de 12:00 et une heure maximum de 18:00:

<form>
  <label for="appt-time">Veuillez choisir une heure de rendez-vous (heures d'ouverture 12:00 à 18:00) : </label>
  <input id="appt-time" type="time" name="appt-time"
         min="12:00" max="18:00">
  <span class="validity"></span>
</form>

Voici la feuille de style CSS utilisée dans l'exemple précédent. On utilise les pseudos-classes :valid et :invalid afin de mettre en forme le contrôle selon que la valeur saisie est valide ou non. Les icônes qui indiquent cette validité ont été placées dans un élément <span> à part car Chrome ne permet pas de placer du contenu généré dans le contrôle.

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;
}

Avec ce fragment de code HTML :

  • Seules les heures comprises entre 12:00 et 18:00 sont affichées comme étant valides (les heures avant et après seront invalides).
  • Selon le navigateur utilisé, il peut même être impossible de sélectionner une heure en dehors de la plage restreinte (avec Edge notamment).

Rendre la saisie obligatoire

On peut également utiliseer l'attribut required afin que la saisie du champ soit obligatoire. Lorsque c'est le cas, les navigateurs afficheront un message d'erreur si l'utilisateur tente d'envoyer le formulaire sans avoir saisi de valeur (ou si celle-ci est en dehors de la plage indiquée).

Prenons l'exemple suivant qui restreint la plage horaire sélectionnable et qui rend le champ obligatoire :

<form>
  <div>
    <label for="appt-time">Veuillez choisir une heure de rendez-vous (horaires d'ouverture entre 12:00 et 18:00) : </label>
    <input id="appt-time" type="time" name="appt-time"
           min="12:00" max="18:00" required>
    <span class="validity"></span>
  </div>
  <div>
      <input type="submit" value="Envoyer le formulaire">
  </div>
</form>

Si vous essayez de soumettre le formulaire sans avoir saisi de valeur (ou avec une heure en dehors des heures d'ouverture indiquées), le navigateur affichera une erreur. Vous pouvez manipuler le résultat obtenu :

Voici une capture d'écran (en anglais) si votre navigateur ne prend pas en charge cete fonctionnalité :

Attention ! Il est également important de vérifier le format de la valeur saisie côté serveur ! En effet, il est tout à fait possible pour un utilisateur de modifier le code HTML du site ou d'envoyer des données au serveur sans passer par le formulaire. Il est donc nécessaire de contrôler la valeur avant de s'en servir dans la logique de l'application côté serveur afin d'éviter des conséquences malheureuses.

Gérer la prise en charge des navigateurs

Comme mentionné avant, un problème peut être l'hétérogénéité de la prise en charge des navigateurs : Safari ne prend pas en charge cette fonctionnalité sur les ordinateurs de bureau et les anciennes versions d'Internet Explorer n'implémentent pas cet élément.

Pour les plateformes mobiles (Android et iOS par exemple), les systèmes d'exploitation fournissent des interfaces particulièrement adaptées aux environnements tactiles. Voici par exemple le sélecteur d'heure pour Chrome sur Android :

Lorsqu'un navigateur ne prend pas en charge ce type d'élément, il utilise un champ texte (<input type="text">) à la place. Mais cela crée des problèmes, tant au niveau de l'interface utilisateur que de la cohérence des données et du format.

C'est ce problème de format qui est le plus important. Comme nous l'avons expliqués plus haut, un champtime permet d'obtenir un valeur normalisée, respectant le format hh:mm. Avec un champ texte, le navigateur ne reconnaît pas de format particulier pour l'heure et les utilisateurs peuvent employer différentes formes pour décrire l'heure voulue :

  • 3.00 pm
  • 3:00pm
  • 15:00
  • 3h de l'après-midi
  • etc.

Une façon de contourner ce problème consiste à utiliser l'attribut pattern sur le champ time. Bien quqe le champ  time n'utilise pas cet attribut, le champ texte pourra l'utiliser. Vous pouvez par exemple tester ce fragment de code dans un navigateur qui ne prend pas en charge <input type="time"> :

<form>
  <div>
    <label for="appt-time">Veuillez choisir une heure de rendez-vous (heures d'ouverture entre 12:00 et 18:00) : </label>
    <input id="appt-time" type="time" name="appt-time"
           min="12:00" max="18:00" required
           pattern="[0-9]{2}:[0-9]{2}">
    <span class="validity"></span>
  </div>
  <div>
      <input type="submit" value="Envoyer">
  </div>
</form>

Si on essaie d'envoyer une valeur qui ne respecte pas le bon format, le navigateur affichera un message d'erreur et mettra en évidence le champ si celui-ci ne suit pas la forme nn:nn avec n un nombre entre 0 et 9. Bien entendu, cela n'empêche pas de saisir des heures invalides mais qui respectent ce format.

De plus, comment communiquer à l'utilisateur le format dans lequel saisir l'heure ?

Il reste donc un problème.

Actuellement, la meilleure façon de gérer ce type de saisie pour les différents navigateurs consiste à utiliser deux contrôles (le premier pour la saisie des heures et le second pour la saisie des minutes) avec deux éléments <select> (cf. ci-après) ou d'utiliser certaines bibliothèques JavaScript telles que jQuery date picker ou encore jQuery timepicker plugin.

Exemples

Dans l'exemple qui suit, on crée deux ensembles d'éléments : un sélecteur natif avec <input type="time"> et un ensemble de deux éléments <select> qui permettent de choisir des heures et des minutes dans les navigateurs qui ne prennent pas en charge le contrôle natif.

Voici le fragment HTML utilisé :

<form>
  <div class="nativeTimePicker">
    <label for="appt-time">Veuillez choisir une heure de rendez-vous (heures d'ouverture 12:00 à 18:00) : </label>
      <input id="appt-time" type="time" name="appt-time"
             min="12:00" max="18:00" required>
      <span class="validity"></span>
    </div>
  <p class="fallbackLabel">Veuillez choisir une heure de rendez-vous (heures d'ouverture 12:00 à 18:00) : </p>
  <div class="fallbackTimePicker">
    <div>
      <span>
        <label for="hour">Heures :</label>
        <select id="hour" name="hour">
        </select>
      </span>
      <span>
        <label for="minute">Minutes :</label>
        <select id="minute" name="minute">
        </select>
      </span>
    </div>
  </div>
</form>

Les valeurs pour les heures et les minutes seront générées dynamiquement en JavaScript.

La partie la plus intéressante du code est celle qui permet de détecter si le contrôle natif est pris en charge. Pour cela, on crée un nouvel élément  <input> et on modifie son attribut type afin qu'il vaille time, immédiatement après, on vérifie la valeur du type. Si le navigateur ne prend pas en charge l'élément, il renverra text car l'élément a été transformé en <input type="text">, dans ce cas, on masque le sélecteur natif et on affiche l'interface alternative avec les deux éléments <select>.

// On définit quelques variables
var nativePicker = document.querySelector('.nativeTimePicker');
var fallbackPicker = document.querySelector('.fallbackTimePicker');
var fallbackLabel = document.querySelector('.fallbackLabel');

var hourSelect = document.querySelector('#hour');
var minuteSelect = document.querySelector('#minute');

// On cache le sélecteur alternatif
fallbackPicker.style.display = 'none';
fallbackLabel.style.display = 'none';

// On teste si un nouveau contrôle time 
// est transformé en text
var test = document.createElement('input');
test.type = 'time';
// Si c'est le cas…
if(test.type === 'text') {
  // On masque le sélecteur natif et
  // on affiche le sélecteur alternatif
  nativePicker.style.display = 'none';
  fallbackPicker.style.display = 'block';
  fallbackLabel.style.display = 'block';

  // On génère les valeurs dynamiquement
  // pour les heures et les minutes
  populateHours();
  populateMinutes();
}

function populateHours() {
  // On ajoute les heures dans 
  // l'élément <select> avec les 6 
  // heures ouvertes
  for(var i = 12; i <= 18; i++) {
    var option = document.createElement('option');
    option.textContent = i;
    hourSelect.appendChild(option);
  }
}

function populateMinutes() {
  // On génère 60 options pour 60 minutes
  for(var i = 0; i <= 59; i++) {
    var option = document.createElement('option');
    option.textContent = (i < 10) ? ("0" + i) : i;
    minuteSelect.appendChild(option);
  }
}

// avec la fonction suivante, si l'heure vaut 18
// on s'assure que les minutes vaillent 00
// afin de ne pas pouvoir choisir d'heure passé 18:00
 function setMinutesToZero() {
   if(hourSelect.value === '18') {
     minuteSelect.value = '00';
   }
 }

 hourSelect.onchange = setMinutesToZero;
 minuteSelect.onchange = setMinutesToZero;

Spécifications

Spécification État Commentaires
HTML Living Standard
La définition de '<input type="time">' dans cette spécification.
Standard évolutif  

Compatibilité des navigateurs

Fonctionnalité Chrome Edge Firefox (Gecko) Internet Explorer Opera Safari
Support simple 20 12 57 (57) Pas de support 10.62 Pas de support
Fonctionnalité Android Chrome pour Android Edge Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
Support simple (Oui) (Oui) (Oui) 57.0 (57) ? (Oui) (Oui)

Voir aussi

Étiquettes et contributeurs liés au document

Étiquettes : 
 Contributeurs à cette page : SphinxKnight
 Dernière mise à jour par : SphinxKnight,