Premiers pas avec les animations liées au défilement en CSS

1. Avant de commencer

Les animations liées au défilement vous permettent de contrôler la lecture d'une animation en fonction de la position de défilement d'un conteneur de défilement. Autrement dit, lorsque vous faites défiler la page vers le haut ou vers le bas, l'animation avance ou revient en arrière. En outre, grâce aux animations liées au défilement, vous pouvez contrôler une animation en fonction de la position d'un élément dans son conteneur de défilement. Cela vous permet de créer des effets intéressants, comme une image de fond se déplaçant en parallaxe, des barres de progression de défilement et des images qui sont dévoilées à mesure qu'elles s'affichent à l'écran.

Une nouveauté dans Chrome 114 est la prise en charge d'un ensemble de classes JavaScript et de propriétés CSS qui vous permettent de facilement créer de façon déclarative des animations liées au défilement. Ces nouvelles API fonctionnent conjointement avec les API CSS Animations et Web Animations existantes.

Cet atelier de programmation vous explique comment créer des animations liées au défilement à l'aide de CSS. À la fin de cet atelier, vous vous serez familiarisé avec les nombreuses nouvelles propriétés CSS introduites par cette fonctionnalité intéressante, telles que scroll-timeline, view-timeline, animation-timeline et animation-range.

Points abordés

  • Créer un effet parallaxe pour l'arrière-plan avec une timeline de défilement en CSS
  • Créer une barre de progression avec une timeline de défilement en CSS
  • Créer un effet d'affichage progressif d'une image avec une timeline d'affichage en CSS
  • Cibler différents types de plages d'une timeline d'affichage en CSS

Prérequis

L'une des combinaisons "appareil-logiciel" suivantes :

  • Une version récente de Chrome (114 ou ultérieure) sous ChromeOS, macOS ou Windows
  • Connaissances de base du langage HTML
  • Connaissances fondamentales du langage CSS, particulièrement en ce qui concerne les animations CSS

2. Configuration

Tout ce dont vous aurez besoin pour ce projet se trouve dans un dépôt GitHub. Pour commencer, clonez le code, puis ouvrez-le dans l'environnement de développement de votre choix.

  1. Ouvrez un nouvel onglet de navigateur et accédez à l'adresse https://github.com/googlechromelabs/io23-scroll-driven-animations-codelab.
  2. Clonez le dépôt.
  3. Ouvrez le code dans l'IDE de votre choix.
  4. Exécutez npm install pour installer les dépendances.
  5. Exécutez npm start et accédez à http://localhost:3000/.
  6. Si npm n'est pas installé sur votre ordinateur, ouvrez le fichier src/index.html dans Chrome.

3. En savoir plus sur les timelines des animations

Par défaut, une animation associée à un élément est exécutée sur la timeline du document. Cela signifie que, dès le chargement de la page, la timeline de l'animation progresse au fur et à mesure que le temps passe. Il s'agit de la timeline d'animation par défaut et, jusqu'à présent, elle était la seule que vous pouviez utiliser.

Grâce aux animations liées au défilement, vous avez accès à deux nouveaux types de timelines :

  • Timeline de progression de défilement
  • Timeline de progression d'affichage

En CSS, ces timelines peuvent être associées à une animation à l'aide de la propriété animation-timeline. Découvrez ce que ces nouvelles timelines signifient et ce qui les différencie.

Timeline de progression de défilement

Une timeline de progression de défilement est une timeline d'animation qui est associée à la progression de la position de défilement d'un conteneur de défilement, également appelé zone de défilement, sur un axe particulier. Elle convertit une position dans une plage de défilement en un pourcentage de progression le long d'une timeline.

La position de défilement de début représente 0 % de progression et la position de défilement de fin représente 100 % de progression. Dans la visualisation suivante, notez que la progression augmente de 0 % à 100 % lorsque vous faites descendre la barre de défilement jusqu'en bas.

Timeline de progression d'affichage

Ce type de timeline est associé à la progression relative d'un élément particulier dans un conteneur de défilement. Comme pour la timeline de progression de défilement, c'est le décalage de défilement d'un conteneur de défilement qui est suivi. Mais contrairement à une timeline de progression de défilement, c'est ici la position relative d'un objet dans cette zone de défilement qui détermine la progression. Ce comportement est comparable à celui de IntersectionObserver, qui suit la visibilité d'un élément dans le conteneur de défilement. Si l'élément n'est pas visible dans le conteneur de défilement, il n'y a pas d'intersection. S'il est visible dans le conteneur de défilement, même s'il s'agit d'une toute petite partie, il y a intersection.

La timeline de progression d'affichage démarre dès qu'il y a intersection entre le sujet et le conteneur de défilement et se termine lorsqu'il n'y a plus d'intersection. Dans la visualisation suivante, notez que la progression passe de 0 % à 100 %, entre le moment où le sujet entre dans le conteneur de défilement et celui où il le quitte.

Par défaut, une animation liée à la timeline de progression d'affichage est associée à l'intégralité de sa plage. Le processus commence dès que le sujet entre dans la zone de défilement et se termine lorsqu'il la quitte.

Vous pouvez également associer l'animation à une partie spécifique de la timeline de progression d'affichage en indiquant la portion de plage concernée. Par exemple, il peut s'agir de la phase d'entrée du sujet dans la zone de défilement. Dans la visualisation suivante, la progression commence à partir de 0 % lorsque le sujet entre dans le conteneur de défilement, mais elle atteint déjà 100 % dès que l'intersection est complète.

Vous pouvez cibler les plages de défilement d'affichage cover, contain, entry, exit, entry-crossing et exit-crossing. Ces plages sont expliquées plus tard dans l'atelier, mais si ne souhaitez pas attendre, utilisez l'outil situé à l'adresse https://goo.gle/view-timeline-range-tool pour voir à quoi correspond chaque plage.

4. Créer un effet parallaxe pour l'arrière-plan

Le premier effet à ajouter à la page est un effet d'arrière-plan en parallaxe sur l'image de fond principale. Lorsque vous faites défiler la page, l'image de fond doit aussi bouger, mais à une vitesse différente. Cet effet utilise la timeline de progression de défilement.

Pour l'implémenter, deux étapes sont nécessaires :

  1. Créez une animation qui déplace la position de l'image de fond.
  2. Associez l'animation à la progression de défilement du document.

Créer l'animation

  1. Pour créer l'animation, utilisez un ensemble standard d'images clés. Dans cet ensemble, déplacez la position de l'arrière-plan verticalement de 0 % à 100 % :

src/styles.css

@keyframes move-background {
  from {
    background-position: 50% 0%;
  }
  to {
    background-position: 50% 100%;
  }
}
  1. Associez ensuite ces images clés à l'élément du corps :

src/styles.css

body {
  animation: 1s linear move-background;
}

Avec ce code, l'animation move-background est ajoutée à l'élément du corps. Sa propriété animation-duration est définie sur une seconde (1 s) et un lissage de vitesse linear est utilisé.

Le moyen le plus simple de créer une timeline de progression de défilement consiste à utiliser la fonction scroll(). Cela permet de créer une timeline de progression de défilement anonyme que vous pouvez définir comme valeur de la propriété animation-timeline.

La fonction scroll() accepte les arguments <scroller> et <axis>.

Les valeurs acceptées pour l'argument <scroller> sont les suivantes :

  • nearest : utilise le conteneur de défilement qui est l'ancêtre le plus proche (par défaut).
  • root : utilise la fenêtre d'affichage du document comme conteneur de défilement.
  • self : utilise l'élément lui-même comme conteneur de défilement.

Les valeurs acceptées pour l'argument <axis> sont les suivantes :

  • block : utilise la mesure de la progression sur l'axe de bloc du conteneur de défilement (par défaut).
  • inline : utilise la mesure de la progression sur l'axe d'alignement du conteneur de défilement.
  • y : utilise la mesure de la progression sur l'axe Y du conteneur de défilement.
  • x : utilise la mesure de la progression sur l'axe X du conteneur de défilement.

Pour lier l'animation au conteneur de défilement racine sur l'axe de bloc, les valeurs à transmettre dans scroll() sont root et block : scroll(root block).

  • Définissez scroll(root block) comme valeur de la propriété animation-timeline sur le corps. En outre, puisqu'une valeur animation-duration exprimée en secondes n'a aucun sens, définissez la durée sur auto. Si vous ne spécifiez pas de valeur pour animation-duration, cette propriété sera définie par défaut sur auto.

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(root block);
}

Comme le conteneur de défilement racine est également le parent le plus proche pour l'élément de corps, vous pouvez également utiliser la valeur nearest :

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll(nearest block);
}

Étant donné que nearest et block sont les valeurs par défaut, vous pouvez choisir de les omettre. Dans ce cas, le code peut être simplifié de la façon suivante :

src/styles.css

body {
  animation: linear move-background;
  animation-duration: auto;
  animation-timeline: scroll();
}

Vérifier vos modifications

Si tout s'est déroulé comme prévu, vous devez normalement avoir ceci :

Sinon, reportez-vous à la branche solution-step-1 du code.

5. Créer une barre de progression pour la galerie d'images

La page contient un carrousel horizontal. Il lui manque une barre de progression pour indiquer quelle photo est affichée actuellement.

Le balisage du carrousel ressemble à ceci :

src/index.html

<div class="gallery">
  <div class="gallery__scrollcontainer" style="--num-images: 3;">
    <div class="gallery__progress"></div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
    <div class="gallery__entry">
      ...
    </div>
  </div>
</div>

Les images clés pour la barre de progression sont déjà en place et ressemblent à ceci :

src/styles.css

@keyframes adjust-progress {
  from {
    transform: scaleX(calc(1 / var(--num-images)));
  }
  to {
    transform: scaleX(1);
  }
}

Cette animation doit être associée à l'élément gallery__progress avec une timeline de progression de défilement. Pour ce faire, comme indiqué à l'étape précédente, créez une timeline de progression de défilement anonyme à l'aide de la fonction scroll() :

src/styles.css

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  animation-timeline: scroll(nearest inline);
}

Une autre façon de définir une timeline de progression de défilement consiste à en utiliser une nommée. Bien qu'un peu plus détaillée, cette approche peut être utile lorsque vous ne ciblez pas un conteneur de défilement parent ou racine, ou lorsque la page utilise plusieurs timelines. Vous pouvez ainsi identifier une timeline de progression de défilement par le nom que vous lui donnez.

Pour créer une timeline de progression de défilement nommée sur un élément, définissez avec une valeur de votre choix la propriété CSS scroll-timeline-name sur le conteneur de défilement.

Étant donné que la galerie défile horizontalement, vous devez également définir la propriété scroll-timeline-axis. Les valeurs autorisées sont les mêmes que pour l'argument <axis> de scroll().

Enfin, pour lier l'animation à la timeline de progression de défilement, définissez la propriété animation-timeline de l'élément à animer sur la valeur utilisée pour l'identifiant de scroll-timeline-name.

  • Modifiez le fichier styles.css de façon à inclure ceci :

src/styles.css

.gallery__scrollcontainer {
  /* Create the gallery-is-scrolling timeline */
  scroll-timeline-name: gallery-is-scrolling;
  scroll-timeline-axis: inline;
}

.gallery__progress {
  animation: linear adjust-progress;
  animation-duration: auto;
  /* Set gallery-is-scrolling as the timeline */
  animation-timeline: gallery-is-scrolling;
}

Vérifier vos modifications

Si tout s'est déroulé comme prévu, vous devez normalement avoir ceci :

Sinon, reportez-vous à la branche solution-step-2 du code.

6. Animer les images de la galerie lorsqu'elles entrent dans la zone de défilement ou la quittent

Configurer une timeline de progression d'affichage anonyme

Un effet intéressant à ajouter est l'ouverture en fondu des images de la galerie lorsqu'elles entrent dans la zone d'affichage. Pour ce faire, utilisez une timeline de progression d'affichage.

Pour créer une timeline de progression d'affichage, vous utilisez la fonction view(). Les arguments acceptés sont <axis> et <view-timeline-inset>.

  • <axis> est le même argument que pour la timeline de progression de défilement. Il définit l'axe à suivre.
  • Avec <view-timeline-inset>, vous pouvez spécifier un décalage (positif ou négatif) pour ajuster les délimitations déterminant si un élément est considéré dans l'affichage ou non.
  • Les images clé sont déjà en place. Il vous suffit de les associer. Pour ce faire, créez une timeline de progression d'affichage sur chaque élément .gallery__entry.

src/styles.css

@keyframes animate-in {
  from {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  to {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Limiter la plage d'une timeline de progression d'affichage

Si vous enregistrez le CSS et que vous chargez la page, vous voyez que les éléments apparaissent en fondu, mais il semble y avoir un problème. Leur opacité de début est de 0 lorsqu'ils sont non visibles et leur opacité de fin est seulement de 1 lorsqu'ils ont complètement quitté la zone de visibilité.

Cela est dû au fait que la plage par défaut d'une timeline de progression d'affichage est la plage complète. Cette plage est appelée cover.

  1. Pour cibler uniquement la plage entry du sujet, utilisez la propriété CSS animation-range pour limiter les situations où l'animation doit être exécutée.

src/styles.css

.gallery__entry {
  animation: linear fade-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry 0% entry 100%;
}

L'animation est maintenant exécutée de entry 0% (le sujet est sur le point d'entrer dans le conteneur de défilement) à entry 100% (le sujet est complètement à l'intérieur du conteneur de défilement).

Vous pouvez utiliser les plages de timeline d'affichage suivantes :

  • cover : représente la plage complète de la timeline de progression d'affichage.
  • entry : représente la plage pendant laquelle la zone principale entre dans la plage de visibilité de la progression d'affichage.
  • exit : représente la plage pendant laquelle la zone principale quitte la plage de visibilité de la progression d'affichage.
  • entry-crossing : représente la plage pendant laquelle la zone principale croise le cadre de la bordure de début.
  • exit-crossing : représente la plage pendant laquelle la zone principale croise le cadre de la bordure de fin.
  • contain : représente la plage pendant laquelle la zone principale est entièrement incluse dans (ou couvre complètement) sa plage de visibilité de la progression d'affichage dans le conteneur de défilement. Cela dépend si le sujet est plus grand ou plus petit que le conteneur de défilement.

Utilisez l'outil situé à l'adresse https://goo.gle/view-timeline-range-tool pour voir à quoi correspond chaque plage, et comment les pourcentages affectent les positions de début et de fin.

  1. Puisque les plages de début et de fin sont les mêmes dans cet exemple et que les décalages par défaut sont utilisés, simplifiez animation-range et utilisez un seul nom de plage d'animation :

src/styles.css

.gallery__entry {
  animation: linear animate-in;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry;
}
  • Pour fermer les images en fondu lorsqu'elles quittent le conteneur de défilement, procédez comme vous l'avez fait avec l'animation animate-in, mais ciblez une plage différente.

src/styles.css

@keyframes animate-out {
  from {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  to {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}

.gallery__entry {
  animation: linear animate-in, linear animate-out;
  animation-duration: auto;
  animation-timeline: view(inline);
  animation-range: entry, exit;
}

Les images clés animate-in seront appliquées à la plage entry et les images clés animate-out à la plage exit.

Vérifier vos modifications

Si tout s'est déroulé comme prévu, vous devez normalement avoir ceci :

Sinon, reportez-vous à la branche solution-step-3 du code.

7. Animer les images de la galerie lorsqu'elles entrent dans la zone de défilement ou la quittent à l'aide d'un ensemble d'images clés

Utilisation d'un ensemble d'images clés

Au lieu d'associer deux animations à des plages différentes, vous pouvez créer un ensemble d'images clés qui contient déjà les informations de plage.

Les images clés ressemblent à ceci :

@keyframes keyframes-name {
  range-name range-offset {
    ...
  }
  range-name range-offset {
    ...
  }
}
  1. Pour combiner les images clés de fondu à l'ouverture et de fondu à la fermeture, procédez comme suit :

src/styles.css

@keyframes animate-in-and-out {
  entry 0% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
  entry 90% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }

  exit 10% {
    opacity: 1;
    clip-path: inset(0% 0% 0% 0%);
  }
  exit 100% {
    opacity: 0;
    clip-path: inset(50% 0% 50% 0%);
  }
}
  1. Lorsque les informations de plage sont présentes dans les images clés, vous n'avez plus besoin de spécifier animation-range séparément. Associez les images clés comme pour la propriété animation.

src/styles.css

.gallery__entry {
  animation: linear animate-in-and-out both;
  animation-duration: auto;
  animation-timeline: view(inline);
}

Vérifier vos modifications

Si tout s'est déroulé comme prévu, vous devez normalement avoir le même résultat qu'à l'étape précédente. Sinon, reportez-vous à la branche solution-step-4 du code.

8. Félicitations !

Vous avez terminé cet atelier de programmation. Vous savez maintenant comment créer des timelines de progression de défilement et des timelines de progression d'affichage en CSS.

En savoir plus

Ressources :