Créer une horloge responsive en full-CSS

Créer une horloge responsive en full-CSS

Lorsque nous avons démarré le développement du jeu éducatif Table Speed (disponible sur iOS/Android ici http://www.tablespeed.fr, nous avons vite été confrontés à une nouvelle problématique :


Comment réaliser une horloge responsive (qui s’adapte à la largeur de l’écran sur lequel elle s’affiche) ?


Et comme chez AKTARMA on aime bien partager, voilà comment nous avons réalisé une horloge intégralement en CSS en s’aidant du pré-processeur SASS.

Pour celles et ceux d’entre vous qui n’utilisent pas SASS, le code CSS compilé automatiquement est disponible sur codepen.io très facilement en choisissant l’option “View compiled CSS”:

Codepen - Modifier l'affichage du volet CSS
Codepen - Modifier l'affichage du volet CSS

Mise en place du fond de l’horloge

Dans un fichier HTML, écrire le code suivant :

<div class="clock">
</div>

Il s'agit ici de la <div> qui regroupera tous les éléments de notre horloge. Profitons-en pour la styliser un peu grâce à SASS. Pour cela, nous allons créer un fichier SCSS (une des extensions de fichiers possibles de SASS) qui contiendra deux variables pour commencer :

//VARIABLES
$clock_size : 400px;
$clock_color : #30507b;

Ensuite, donnons du style à notre horloge :

.clock{
  position:relative;
  margin:auto;
  height:$clock_size;
  width:$clock_size;
  border: 8px solid $clock_color;
  border-radius:50%;
}

Ici, nous mettons notre horloge en “position : relative” pour pouvoir travailler facilement de futurs éléments qui seront en position :absolute”. Le “margin :auto” n’est pas obligatoire, il nous permet juste de centrer l’horloge dans la page pour la démonstration.
Ensuite, nous lui donnons une hauteur et une largeur définies en variables ($clock_size). L’utilisation des variables plutôt que de valeurs brutes (du style 400px) permet d’adapter en un tour de main notre horloge au projet sur lequel on souhaite l’utiliser.
Nous marquons les bords de l’horloge en lui mettant une bordure pleine de 8px de large et d’une couleur définie elle aussi en variable ($clock_color).
Enfin, pour arrondir notre horloge nous lui mettons un border-radius de 50%.

Voilà le résultat :

See the Pen horloge CSS base by GRATTERY Vincent (@vgrattery) on CodePen.

L’heure, c’est l’heure !

Il est maintenant temps d'afficher l’heure ainsi que ses index (c’est le nom des petits traits symbolisant les heures tout autour de l’horloge).

Pour ce faire, nous allons d’abord créer une première <div> qui comporte la classe “hour” avec une nouvelle div dedans qui comporte la classe “time_number” et un numéro d’heure dedans (donc un chiffre entre 1 et 12, vous suivez ?).

<div class="clock">
  <div class="hour">
    <div class="time_number">1</div>
  </div>
</div>

Donnons maintenant du style à tout ça.

Ajoutons un léger fond rouge à notre div.hour pour visualiser le résultat de ce que l’on fait. Ce fond sera enlevé plus tard.

//VARIABLES SUPPLEMENTAIRES
$hour_width: 50px;
$hour_index_width: 4px;
$hour_index_height: 20px;

.hour{
  background:rgba(red, 0.4);
  position:absolute;
  top:0;
  bottom:0;
  width: $hour_width;
  left:50%;
  margin-left: -$hour_width/2;
  &:before{
    content:"";
    position:absolute;
    left:50%;
    top:10px;
    width: $hour_index_width;
    height:$hour_index_height;
    margin-left: -$hour_index_width/2;
    background: $clock_color;
  }
  .time_number{
    font-family:arial;
    text-align:center;
    color:$clock_color;
    font-size:25px;
    margin-top: $hour_index_height+20;
  }
}

La div .hour doit être en “position: absolute” pour que nous puissions la positionner comme on veut ensuite. Nous pouvons donc ensuite la placer sur toute la hauteur grâce à un “top” et un “bottom” à 0.

Nous lui donnons une largeur fixe définie en variable ($hour_width) et nous plaçons la div au centre de l’horloge grâce à un “left:50%” auquel nous ajoutons un “margin-left: -$hour_index_width/2” qui permet de redécaler la div vers la droite de la moitié de la largeur.

Voilà, notre div est centrée, passons à l’index de l’heure (vous vous rappelez, il s’agit du petit trait qui symbolise l’emplacement exact de l’heure sur le cadran).

Pour ne pas surcharger le code HTML inutilement, passons par l’élément :before proposé par CSS.

Celui ci est également en “position: absolute" et nous le décalons du haut de l’horloge grâce à un “top: 10px”. Nous le centrons grâce à la même technique que celle utilisée précédemment sauf que la variable utilisée est $hour_index_width. Nous lui donnons une hauteur et une largeur définies également en variable ($hour_index_width et $hour_index_height) et nous lui donnons la même couleur que la bordure de l’horloge ($clock_color).

Enfin, il nous reste à rendre esthétique le numéro de l’heure. Pour cela, rien de plus simple. On lui donne la même couleur que la bordure de l’horloge ($clock_color), nous centrons le texte horizontalement et définissons la police et la taille de caractère utilisées.

Enfin nous l’écartons également de l’index de l’heure grâce à un “margin-top: $hour_index_height+20;”

Voilà le résultat :

See the Pen horloge CSS avec une heure. by GRATTERY Vincent (@vgrattery) on CodePen.

Faisons le tour du cadran

Plaçons maintenant toutes les heures dans le fichier HTML. Un simple copier/coller une douzaine de fois suffira. Pensez simplement à remplacer les numéros d’heure. Pour les plus aguerris, une simple boucle PHP suffira.

<div class="clock">
  
  <div class="hour">
    <div class="time_number">1</div>
  </div>
  <div class="hour">
    <div class="time_number">2</div>
  </div>
  <div class="hour">
    <div class="time_number">3</div>
  </div>
  <div class="hour">
    <div class="time_number">4</div>
  </div>
  <div class="hour">
    <div class="time_number">5</div>
  </div>
  <div class="hour">
    <div class="time_number">6</div>
  </div>
  <div class="hour">
    <div class="time_number">7</div>
  </div>
  <div class="hour">
    <div class="time_number">8</div>
  </div>
  <div class="hour">
    <div class="time_number">9</div>
  </div>
  <div class="hour">
    <div class="time_number">10</div>
  </div>
  <div class="hour">
    <div class="time_number">11</div>
  </div>
  <div class="hour">
    <div class="time_number">12</div>
  </div>
</div>

Rentrons enfin dans le nœud du problème : placer automatiquement les heures à leur place grâce à SASS.

Mais avant de passer au code, mettons en place la logique :

Il y a douze heures sur un cadran qui tourne à 360° autour d’un axe central (celui qui retient les aiguilles en général).

360°/12 = 30°. Il nous faut donc afficher une heure tous les 30° sur l’horloge.

Pour cela, il nous faut créer une boucle qui applique une rotation de 30° supplémentaires à chaque div.hour par rapport à sa précédente.

SASS permet de créer une boucle automatique de ce genre :

@for $i from 1 through 12 {
  &:nth-child(#{$i}) {
    transform:rotate(#{30*$i}deg);
  }
}

Ici, nous disons à SASS de faire une rotation de 30x$i degrés pour chaque valeur “i” comprise entre 1 et 12.

C’est pas mal mais ça ne suffit pas puisque le chiffre de l’heure tourne aussi.

Voilà le résultat :

See the Pen horloge CSS avec les heures - Step 1 by GRATTERY Vincent (@vgrattery) on CodePen.

Rajoutons donc une rotation inverse à chacune des div .time_number afin qu’elle se remette dans le bon sens :

@for $i from 1 through 12 {
  &:nth-child(#{$i}) {
    transform:rotate(#{30*$i}deg);
    .time_number{
      transform:rotate(#{-30*$i}deg);
    }
  }
}

Voilà le résultat :

See the Pen horloge CSS avec les heures - Step 2 by GRATTERY Vincent (@vgrattery) on CodePen.

Les aiguilles

Le plus dur est fait mais il est temps de rajouter les aiguilles en CSS. Avant cela, nous pouvons supprimer le fond rouge de la div .hour. Notre horloge est maintenant propre.

Côté HTML, c’est encore une fois assez simple puisqu’il suffit de rajouter deux div (.hour_pointer et .minute_pointer) en fin de page, juste avant la fermeture de la div .clock.

<div class="clock">
  
  <div class="hour">
    <div class="time_number">1</div>
  </div>
  <div class="hour">
    <div class="time_number">2</div>
  </div>
  <div class="hour">
    <div class="time_number">3</div>
  </div>
  <div class="hour">
    <div class="time_number">4</div>
  </div>
  <div class="hour">
    <div class="time_number">5</div>
  </div>
  <div class="hour">
    <div class="time_number">6</div>
  </div>
  <div class="hour">
    <div class="time_number">7</div>
  </div>
  <div class="hour">
    <div class="time_number">8</div>
  </div>
  <div class="hour">
    <div class="time_number">9</div>
  </div>
  <div class="hour">
    <div class="time_number">10</div>
  </div>
  <div class="hour">
    <div class="time_number">11</div>
  </div>
  <div class="hour">
    <div class="time_number">12</div>
  </div>
  <div class="hour_pointer"></div>
  <div class="minute_pointer"></div>
</div>

Préparons les trois variables nécessaires à la mise en place des horloges :

$hour_pointer_width: 4px;
$minute_pointer_color: #e74011;
$hour_pointer_color: #5bc0c9;

Le but pour toute aiguille qui souhaite se rendre utile c’est de tourner encore et encore. Pour cela, préparons une animation qui la fera tourner de 0° à 360° :

//ANIMATIONS
@keyframes spin {
    from {transform:rotate(0deg);}
    to {transform:rotate(360deg);}
}

Minute papillon !

Donnons maintenant du style à notre aiguille des minutes :

 .minute_pointer{
    position:absolute;
    top:0;
    bottom:0;
    width:$hour_pointer_width;
    left:50%;
    margin-left:-$hour_pointer_width/2;
    animation-name: spin;
    animation-duration: 50000ms;
    animation-iteration-count: infinite;
    animation-timing-function: linear;
    &:before{
      content:"";
      position:absolute;
      width: $hour_pointer_width*4;
      height: $hour_pointer_width*4;
      background:$minute_pointer_color;
      border-radius:50%;
      top:50%;
      left:50%;
      margin-top:-$hour_pointer_width*2;
      margin-left:-$hour_pointer_width*2;
    }
    &:after{
      content:"";
      position:absolute;
      background:$minute_pointer_color;
      top:20px;
      bottom:$clock_size/2.3;
      width:$hour_pointer_width;
    }
  }

Comme pour l’affichage des heures, nous allons utiliser un bloc invisible qui tournera autour de l’axe central de l’horloge. Pour cela, nous le plaçons en “position: absolute” et nous le centrons avec notre technique habituelle en utilisant la variable $hour_pointer_width.

Puis nous lui appliquons l’animation que nous avons préparé :

animation-name: spin;
animation-duration: 50000ms;
animation-iteration-count: infinite;
animation-timing-function: linear;

Ici, nous disons à notre div d’utiliser l’animation “spin”, de l’appliquer sur une durée de 50000ms (la valeur est complètement arbitraire) et de la répéter indéfiniment de manière linéaire.

Pour le moment, nous n’avons créé que le contenant transparent de l’aiguille. Continuons avec sa fixation (le petit rond au centre de l’horloge).

Une fois n’est pas coutume, nous allons utiliser l’élément :before en “position: absolute”. Il fera quatre fois la largeur de la future aiguille, la même valeur en hauteur et la même couleur.

width: $hour_pointer_width*4;
height: $hour_pointer_width*4;
background:$minute_pointer_color;

Pour le rendre sphérique (c’est beaucoup mieux pour un rond) nous lui appliquons un border-radius de 50% puis nous le centrons dans la div grâce à la technique habituelle. Cette fois-ci, cette technique est appliquée également pour le centrage vertical.

top:50%;
left:50%;
margin-top:-$hour_pointer_width*2;
margin-left:-$hour_pointer_width*2;

Passons maintenant à l’aiguille elle-même. L’élément :before étant déjà utilisé, prenons :after.

Toujours en “position: absolute”, nous le placons à 20px du haut grâce à l’attribut “top” et nous lui appliquons une largeur définie en variable ($hour_pointer_width) ainsi qu’une couleur, en variable elle-aussi ($minute_pointer_color).

Enfin, nous plaçons le bas de l’aiguille grâce à une opération mathématique qui aura pour but de laisser une queue après l’axe de l’horloge “bottom:$clock_size/2.3”.

C’est l’heure de finir notre horloge

Pour l’horloge des heures, pas besoin de recommencer tout ça. Le travail effectué pour l’horloge des minutes va pouvoir être repris automatiquement dans son intégralité grâce à SASS :

.hour_pointer{
  @extend .minute_pointer;
}

Du coup, nous n’avons plus qu’à écraser les valeurs que nous souhaitons modifier en procédant de cette manière :

.hour_pointer{
  @extend .minute_pointer;
  animation-duration: 600000ms;
  &:after{
    top:$clock_size/4;
    background:$hour_pointer_color;
  }
}

Ici, nous modifions la durée de l’animation en la multipliant par 12 par rapport à celle de l’aiguille des minutes, soit 600 000ms.

Nous modifions également la hauteur de l’aiguille de l’heure pour la rendre plus petite ainsi que sa couleur.

Et voilà une jolie horloge en CSS !

See the Pen horloge CSS finale by GRATTERY Vincent (@vgrattery) on CodePen.



Si ce tutoriel vous a plu, n’hésitez pas à nous le faire savoir via Twitter (https://twitter.com/Aktarma_fr) ou Facebook (https://www.facebook.com/aktarma.fr/).

|
Pinterest