Créer une animation de « count-up » pour Basti Ui

Le 6 août 2024, Basti Ui, l’incroyable youtubeur UX/UI, publie un tweet en questionnant les quoicou-développeurs :

Le challenge est le suivant arriver à créer une animation CSS d’incrémentation comme de nombreux sites pour suivre des évolutions. Example : Compteur d’abonné Youtube

Les points importants

Pour ce challenge, il va falloir faire attention à plusieurs points :

  • Pas de Javascript (Basti Ui ne connais pas le Javascript et veut pouvoir comprendre le code)
  • Un code simple (Tous pareil qu’au dessus, Basti Ui connais CSS et HTML mais n’est pas un développeur)
  • L’animation doit commencer au chargement de la page
  • Le nombre affiché doit pouvoir être facilement changeable dans le code (le nombre sera changé grâce à une API / valeur géré par un service tiers)

Première étape : comprendre la structure actuelle

La structure actuelle est simple, c’est une page HTML et un peu de CSS. La partie HTML qui nous intéresse est la <div> avec la classe percentage . Elle posède le nombre à incrémenter dans une balise <span> et le caractère %

<div class="percentage"><span>18</span>%</div>

Au niveau du CSS, il y a uniquement des transformations au niveau du texte

.percentage {
  font-size: 80px;
  font-weight: bold;
  color: #000;
}

La structre n’est pas compliqué et permettra de modifier ou ajouter le CSS et HTML sans casser quoi que ce soit

Le résultat

Voici le code que j’ai réalisé. Il comporte plusieurs parties importantes que je vais détailler plus bas.

HTML

<div class="percentage"><span><span id="tens" data-value="18"><span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span></span><span id="units" data-value="18"><span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span></span></span>%</div>

Le code est illisible comme ça mais c’est important de mettre les <span> côte à côte, sinon il y aura des espaces non désirés entre les différents caractères. Voici une version du code plus lisible (attention elle donnera des espaces autour des chiffres)

<div class="percentage">
  <span>
    <span id="tens" data-value="18">
      <span>0</span>
      <span>1</span>
      <span>2</span>
      <span>3</span>
      <span>4</span>
      <span>5</span>
      <span>6</span>
      <span>7</span>
      <span>8</span>
      <span>9</span>
    </span>
    <span id="units" data-value="18">
      <span>0</span>
      <span>1</span>
      <span>2</span>
      <span>3</span>
      <span>4</span>
      <span>5</span>
      <span>6</span>
      <span>7</span>
      <span>8</span>
      <span>9</span>
    </span>
  </span>
  %
</div>

CSS

Ensuite, voici le CSS qui place les éléments comme sur la version originale mais en prennant en compte la nouvelle structure HTML


#units,
#tens {
  display: inline-flex;
  flex-direction: column;
  overflow: hidden;
  line-height: 1;
  height: 1em;
}

#units[data-value$="1"] > *,
#tens[data-value^="1"] > * {
  animation: slide1 1.5s forwards;
}

#units[data-value$="2"] > *,
#tens[data-value^="2"] > * {
  animation: slide2 1.5s forwards;
}

/* pareil 9 fois */

#units[data-value$="9"] > *,
#tens[data-value^="9"] > * {
  animation: slide8 1.5s forwards;
}

@keyframes slide1 {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-100%);
  }
}

@keyframes slide2 {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-200%);
  }
}

/* pareil 9 fois */

@keyframes slide9 {
  0% {
    transform: translateY(0);
  }
  100% {
    transform: translateY(-900%);
  }
}

L’attribut data-value

L’attribut data-value permet de transmettre des données du HTML vers le CSS. Il est aussi possible d’utiliser une classe, le code HTML aurai été <span id="tens" class="value-18">.

En utilisant l’attribut data-value on rend la variable dynamic. Il suffit de changer la valeur de data-value et l’animation s’adapte au nouveau nombre.

Dans le CSS, on selectionne la bonne animation grâce au selecteur suivant.

#units[data-value$="1"] > *,
#tens[data-value^="1"] > * {
  animation: slide1 1.5s forwards;
}

On remarque que le selecteur est différent entre les décimals et les unités. Le $ dans [data-value$="1"] sélectionne les data-value qui commence par 1 et avec * c’est les data-value qui finissent par 1

Préparation pour l’animation

Dans le HTML, chaque chiffre est présent. Cela permet de pouvoir les voir lorsque l’animation se joue.

Ensuite, le CSS met en colonne les chiffres des unités grâce à display: flex; mais sans changer la taille ou les styles adjacent. Cela fonctionne en bloquant la hauteur de #units et #tens (line-height: 1; et height: 1em;)

Enfin, on remonte les chiffre de x fois la taille afin d’afficher le chiffre x. Si on remonte les éléments de 800%, le chiffre 8 sera visible (transform: translateY(-900%);)

L’animation

Pour animer, il suffit d’ajouter une animation CSS qui fera défiler les chiffres.

#units > * {
  animation: slide 1.5s forwards;
} @keyframes slide { 0% { transform: translateY(0); } 100% { transform: translateY(-600%); } }

L’animation ce joue dès que la page est chargé. Le chiffre affiché à la fin de l’animaiton reste visible grâce à la propriété forwards.

Conclusion

En définisant les attentes et en décomposant le projet en plusieurs étapes clées, on peut arriver à faire des choses qui paraissent complexe au premier abord. Ce projet peut paraître compliqué en apparence (rendre dynamic du CSS) mais en décomposant en petites étapes on arrive à résoudre le problème sans Javascript.

Vous pouvez voir le résulat ici : Avant/après animation count-up pour Basti Ui

Publié le 26 août 2024 et modifié le 11 septembre 2024

N'hésitez pas donner votre avis par mail ou sur mes réseaux