aller au contenu principal

Découverte des Scroll-Linked Animations

Des animations câblées sur la chronologie de la scrollbar


Publié le 20/12/2022 dans Blog
Crédit photo - Unsplash - Lukas BatoCrédit photo : Unsplash - Lukas Bato
Je suis en train d'écrire un cours complet sur Flexbox. Il y aura un module entier sur la compréhension de ce mode de layout, et un module 100% pratique avec plus d'une dizaine d'exercices.Tu peux consulter le programme et à te préinscrire dès maintenant ! ⬇️Se préinscrire

Dans cet article je te propose de découvrir les Scroll-Linked Animations. Une spécification CSS encore expérimentale (on met ses gants et ses lunettes de protection svp ! 👨‍🔬) qui permet de faire des animations au scroll en CSS.

Là tu peux te dire :

"euh.. on fait ça depuis 15 ans en JS c'est.. nul ton truc.. 🙄"

Alors non c'est pas nul du tout, voyons ensemble pourquoi.

En JavaScript on fait ce qu'on appelle des Scroll Triggered Animations, en clair des animations déclenchées par le scroll, avec l'API Intersection Observer par exemple.

Les Scroll-Linked Animations c'est différent, elles vont nous permettre de créer une "connexion" directe entre la scrollbar et une animation.

C'est pour cela que ça s'appelle Scroll-"Linked" Animations.

Alors oui, créer une connexion entre le scroll et une animation c'est possible en JavaScript, en récupérant la quantité de scroll effectuée en pourcentage, et en se servant de ce celui-ci pour l'affecter à un élément en CSS.

Mais avec les Scroll-Linked Animations, il sera possible de le faire rien qu'en CSS, en dehors du main thread, donc en terme de performance c'est une très bonne chose !

L'animation se comportera comme une vidéo que l'on joue en mettant lecture ou pause. La "lecture" de l'animation se fera au scroll.

Prenons l'exemple d'un film
Si tu accélères la vidéo alors le film avancera plus vite !
C'est pareil avec les Scroll-Linked Animations, si tu accélères ta vitesse de scroll, ton animation se jouera vite, et si tu arrêtes de scroller, l'animation s'arrêtera aussi.
C'est pour cette raison que l'on perd toute notion de durée d'animation et de easing, cela n'a plus de sens ici. 🙂

Il faut également savoir que par défaut les animations sont câblées sur la timeline du document, c'est pour cela qu'une animation se lance toute seule quand on charge une page.

Qu'est-ce que la timeline du document ?

C'est tout simplement la chronologie du document, pour la connaître, tu peux ouvrir la console du navigateur et taper document.timeline.currentTime. Tu obtiendras le temps écoulé en milliseconde depuis le chargement de la page.

À la différence de date.now() qui commence au 1er janvier 1970, document.timeline commence à 0.

Donc si tu charges une page et que tu attends 1 seconde, la timeline du document sera de 1000.

Une autre timeline, celle de la scrollbar

Reprenons, si par défaut une animation est câblée sur la timeline du document, pour avoir une animation au scroll il nous suffirait de la câbler sur une autre timeline : celle de la scrollbar !

Cette timeline a d'ailleurs un petit nom, c'est la Scroll Progress Timeline, sa valeur s'exprime en pourcentage de progression. Donc lorsqu'on est positionné tout en haut d'une page, la Scroll Progress Timeline est de 0%, à l'inverse si on scroll tout en bas de la page, elle sera à 100%.

La Scroll Progress Timeline ne reste pas bloquée à 100%, si une fois arrivé tout en bas d'une page tu décides de scroller vers le haut, tu vas alors faire "remonter" la timeline ! Comme si tu revenais en arrière pour revoir la scène d'un film.

Je pense que tu commences à comprendre où est-ce que je veux en venir non ? 🙂

Avec les Scroll-Linked Animations il n'y a donc pas de déclenchement d'animation. Le terme "déclenchement" n'est pas vraiment approprié, car cela sous-entend que le scroll enclenche une animation et que cette dernière se joue indépendamment du reste. Un peu comme lorsque l'utilisateur arrive à une certaine quantité de scroll effectuée, qui déclenche l'animation d'un élément.

Avec les Scroll-Linked Animations, il n'y a pas de "déclenchement" d'animation car celle-ci commence dès que l'utilisateur scroll, et se termine quand la Scroll Progress Timeline est à 100%, ou se met en pause si l'utilisateur s'arrête de scroller (rappelle toi c'est comme une vidéo que tu peux avancer ou mettre en pause).

Autrement dit : si une animation est cablée sur la Scroll Progress Timeline du document HTML, si on scroll de 50% de la hauteur du document, alors l'animation aura été jouée de 50%.

Voila ça c'est pour la théorie, j'imagine que c'est peut-être un peu compliqué à comprendre, passons donc à la pratique avec un exemple.

Réalisation d'une barre de progression

On va réaliser une barre de progression qui se remplit lorsqu'on scroll. Cela permet d'indiquer à notre utilisateur de façon visuelle sa progression sur la page, lors de la lecture d'un article par exemple.

Une barre de progression fixée en haut de la page qui se remplit lorsque l'utilisateur scroll

On a besoin de 3 choses :

  • une animation CSS (keyframes)
  • une Scroll Progress Timeline (facile il suffit d'avoir suffisamment de contenu pour avoir une scrollbar)
  • un lien entre les deux (on va utiliser la propriété animation-timeline et la fonction scroll()).

Pour commencer le code HTML, une simple div suffit :

  <div id="scroll-progress"></div>

Ensuite le code CSS :

@keyframes grow-progress {
  from {
    transform: scaleX(0);
  }
  to {
    transform: scaleX(1);
  }
}
#scroll-progress {
  animation: grow-progress 1s linear forwards;
  animation-timeline: scroll(block root);
}

L'animation est une keyframes à laquelle je fais référence dans ma propriété animation. Si je ne fais rien d'autre, mon animation sera joué au chargement de la page, pour éviter cela je câble mon animation sur la Scroll Progress Timeline avec animation-timeline.

En valeur de animation-timeline, j'utilise la fonction scroll(), qui peut prendre deux paramètres : l'axe et le "scroll container".

Dans l'exemple j'ai mis block pour préciser que mon axe est vertical, et root car je veux que mon "scroll container" soit mon document HTML.

block et nearest sont les paramètres par défaut de la fonction scroll(). nearest permet de cibler le premier parent qui a une scrollbar. Dans cet exemple, on peut imaginer que la div est positionnée juste après le body.

On peut donc simplifier le code en ne mettant rien dans la fonction scroll() :

#scroll-progress {
  animation: grow-progress 1s linear forwards;
  animation-timeline: scroll();
}

"Attends mais tu as dis qu'il n'y avait plus du durée à définir car l'animation est câblée sur la timeline de la scrollbar, pourtant je vois qu'il y a une durée de 1 seconde avec un linear dans le code CSS."

Bien vu ! 🙂 La durée de 1 seconde et le easing linear sont ici ignorés, l'animation peut durer 10 secondes comme 10 minutes, cela dépend du temps que l'on met à la jouer en scrollant.

Seulement, quand j'ai fait mes tests, je devais préciser une durée et un easing, sinon cela ne fonctionnait pas. 🤨

Rappel
L'animation est câblée sur la timeline (chronologie) de la scrollbar ! 🙂
Je reprends l'exemple du film, si tu le regarde en vitesse x0,25 tu vas mettre beaucoup plus longtemps à le finir qu'en vitesse x2 !

Si tu veux tester le code tu peux aller sur ce CodePen que j'ai réalisé. Pour que cela fonctionne bien, tu dois t'assurer que ton navigateur est compatible, pour vérifier cela tu peux aller sur le site Can I Use.

Au moment où j'écris ces lignes, le support est à 0% (j'avais dit que c'était expérimental ! 🙂), mais j'ai quand même pu tester les Scroll-Linked Animations avec le navigateur Chrome Canary avec le flag "Experimental Web Platform features" activé.

Mais avec une telle nouveautée, on peut se poser la question : est-ce que ce sera possible de reproduire Intersection Observer en CSS, c'est à dire savoir quand un élément est visible ou non dans le viewport ?

Oui ! On n'utilisera pas la Scroll Progress Timeline mais la View Progress Timeline, encore une autre timeline !

On pourra alors "tracker" les éléments qui entrent et sortent du viewport, et les faire apparaître avec une animation.

Mais ça sera l'objet d'un autre article !

Attention la syntaxe à évoluée
Si tu fais des recherches sur les Scroll-Linked Animations, tu risques de tomber sur des exemples qui utilisent une ancienne syntaxe qui a complètement été revue depuis.
Je vais faire au mieux pour maintenir cet article et le mettre à jour si la syntaxe évolue encore.

C'est terminé pour cet article découverte sur les Scroll-Linked Animations, si tu souhaites aller plus loin voici quelques ressources qui m'ont servit pour la rédaction de cet article.

2024 Sébastien Imbert