Quatre nouvelles fonctionnalités CSS pour des animations d'entrée et de sortie fluides

Joey Arhar
Joey Arhar

Le mouvement est au cœur de toute expérience numérique et guide l'utilisateur d'une interaction à l'autre. Mais il y a quelques lacunes dans les animations fluides sur la plateforme Web. Par exemple, vous pouvez animer facilement des animations d'entrée et de sortie, et animer de façon fluide vers et depuis la couche supérieure pour les éléments que l'utilisateur peut ignorer, comme les boîtes de dialogue et les fenêtres pop-up.

Pour combler ces lacunes, Chrome 116 et 117 incluent quatre nouvelles fonctionnalités de plate-forme Web, qui permettent des animations et des transitions fluides pour des propriétés distinctes.

Ces quatre nouvelles fonctionnalités comprennent:

  • Possibilité d'animer display et content-visibility sur la timeline d'images clés (depuis Chrome 116).
  • Propriété transition-behavior avec le mot clé allow-discrete pour permettre les transitions de propriétés discrètes telles que display (à partir de Chrome 117).
  • Règle @starting-style permettant d'animer les effets d'entrée depuis display: none et dans la couche supérieure (à partir de Chrome 117).
  • Propriété overlay permettant de contrôler le comportement de la couche supérieure pendant une animation (à partir de Chrome 117). ## Afficher des animations dans des images clés

À partir de Chrome 116, vous pouvez utiliser display et content-visibility dans les règles d'image clé. Celles-ci s'intervertent au moment où l'image clé se produit. Aucune nouvelle valeur n'est requise pour cela:

.card {
  animation: fade-out 0.5s forwards;
}

@keyframes fade-out {
  100% {
    opacity: 0;
    display: none;
  }
}

L'exemple précédent anime l'opacité à 0 sur une durée de 0,5 s, puis définit l'affichage sur "aucun". De plus, le mot clé forwards garantit que l'animation reste à son état final, de sorte que l'élément auquel elle est appliquée reste display: none et opacity: 0.

Il s'agit d'un exemple simple qui ressemble à ce que vous pouvez faire avec une transition (voir la démonstration dans la section sur la transition). Toutefois, les transitions ne permettent pas de créer des animations plus complexes, comme dans l'exemple suivant:

.card {
  animation: spin-and-delete 1s ease-in forwards;
}

@keyframes spin-and-delete {
  0% {
    transform: rotateY(0);
    filter: hue-rotate(0);
  }
  80% {
    transform: rotateY(360deg);
    filter: hue-rotate(180deg);
    opacity: 1;
  }
  100% {
    opacity: 0;
    display: none;
  }
}

L'animation spin-and-delete est une animation de sortie. La carte tourne d'abord sur l'axe Y, effectue une rotation des teintes, puis passe l'opacité de 1 à 0 dans la timeline à 80%. Enfin, la carte passe de display: block à display: none.

Pour ces animations de sortie, au lieu de les appliquer directement à un élément, vous pouvez configurer un déclencheur pour les animations. Par exemple, vous pouvez associer un écouteur d'événements à un bouton qui déclenche l'application d'une classe par une classe, comme suit:

.spin-out {
   animation: spin-and-delete 1s ease-in forwards;
}
document.querySelector('.delete-btn').addEventListener('click', () => {
 document.querySelector('.card').classList.add('spin-out');
})

L'exemple ci-dessus a maintenant l'état final display:none. Dans de nombreux cas, vous devrez aller plus loin et supprimer le nœud DOM avec un délai avant expiration pour que l'animation se termine en premier.

Ajouter des transitions à des animations discrètes

Contrairement à l'animation de propriétés discrètes avec des images clés, vous devez utiliser le mode de comportement de transition allow-discrete pour les transitions de propriétés discrètes.

La propriété transition-behavior

Le mode allow-discrete permet d'effectuer des transitions discrètes. Il s'agit d'une valeur de la propriété transition-behavior. transition-behavior accepte deux valeurs: normal et allow-discrete.

.card {
  transition: opacity 0.25s, display 0.25s;
  transition-behavior: allow-discrete; /* Note: be sure to write this after the shorthand */
}

.card.fade-out {
  opacity: 0;
  display: none;
}
Remarque: Cette démonstration de transition présente une technique différente de celle de la première démo d'animation, mais elle ressemble visuellement.

Le raccourci transition définit également cette valeur. Vous pouvez donc omettre la propriété et utiliser le mot clé allow-discrete à la fin du raccourci transition pour chaque transition.

.card {
  transition: opacity 0.5s, display 0.5s allow-discrete;
}

.card.fade-out {
  opacity: 0;
  display: none;
}

Si vous animez plusieurs propriétés discrètes, vous devez inclure allow-discrete après chaque propriété que vous souhaitez animer. Exemple :

.card {
  transition: opacity 0.5s, display 0.5s allow-discrete, overlay 0.5s allow-discrete;
}

.card.fade-out {
  opacity: 0;
  display: none;
}

Règle @starting-style pour les animations d'entrée

Jusqu'à présent, nous avons abordé les animations de sortie dans cet article. Pour créer des animations d'entrée, vous devez utiliser la règle @starting-style.

Utilisez @starting-style pour appliquer un style que le navigateur peut rechercher avant d'ouvrir l'élément sur la page. Il s'agit de l'état "avant l'ouverture" (à partir de laquelle vous créez l'animation).

/*  0. BEFORE-OPEN STATE   */
/*  Starting point for the transition */
@starting-style {
  .item {
    opacity: 0;
    height: 0;
  }
}

/*  1. IS-OPEN STATE   */
/*  The state at which the element is open + transition logic */
.item {
  height: 3rem;
  display: grid;
  overflow: hidden;
  transition: opacity 0.5s, transform 0.5s, height 0.5s, display 0.5s allow-discrete;
}

/*  2. EXITING STATE   */
/*  While it is deleting, before DOM removal in JS, apply this
    transformation for height, opacity, and a transform which
    skews the element and moves it to the left before setting
    it to display: none */
.is-deleting {
  opacity: 0;
  height: 0;
  display: none;
  transform: skewX(50deg) translateX(-25vw);
}

Vous disposez maintenant d'un état d'entrée et de sortie pour ces éléments de la liste de tâches:

Animer des éléments vers et depuis la couche supérieure

Pour animer des éléments vers et depuis la couche supérieure, spécifiez @starting-style à l'état "ouvert" pour indiquer au navigateur l'emplacement de l'animation. Pour une boîte de dialogue, l'état d'ouverture est défini avec l'attribut [open]. Pour un pop-over, utilisez la pseudo-classe :popover-open.

Voici un exemple simple de boîte de dialogue:

/*   0. BEFORE-OPEN STATE   */
@starting-style {
  dialog[open] {
    translate: 0 100vh;
  }
}

/*   1. IS-OPEN STATE   */
dialog[open] {
  translate: 0 0;
}

/*   2. EXIT STATE   */
dialog {
  transition: translate 0.7s ease-out, overlay 0.7s ease-out allow-discrete, display 0.7s ease-out allow-discrete;
  translate: 0 100vh;
}

Dans l'exemple suivant, les effets d'entrée et de sortie sont différents. Pour ce faire, créez une animation à partir du bas de la fenêtre d'affichage et quittez l'effet en haut de la fenêtre d'affichage. Il est également écrit avec du code CSS imbriqué pour une encapsulation plus visuelle.

Lorsque vous animez un pop-over, utilisez la pseudo-classe :popover-open au lieu de l'attribut open utilisé précédemment.

.settings-popover {
  &:popover-open {
    /*  0. BEFORE-OPEN STATE  */
    /*  Initial state for what we're animating *in* from, 
        in this case: goes from lower (y + 20px) to center  */
    @starting-style {
      transform: translateY(20px);
      opacity: 0;
    }
    
    /*  1. IS-OPEN STATE  */
    /*  state when popover is open, BOTH:
        what we're transitioning *in* to 
        and transitioning *out* from */
    transform: translateY(0);
    opacity: 1;
  }
  
  /*  2. EXIT STATE  */
  /*  Initial state for what we're animating *out* to , 
      in this case: goes from center to (y - 50px) higher */
  transform: translateY(-50px);
  opacity: 0;
  
  /*  Enumerate transitioning properties, 
      including display and allow-discrete mode */
  transition: transform 0.5s, opacity 0.5s, display 0.5s allow-discrete;
}

overlay établissement

Enfin, pour fondre un popover ou un dialog à partir de la couche supérieure, ajoutez la propriété overlay à votre liste de transitions. popover et dialog échappent les extraits et les transformations ancêtres, et placent le contenu dans la couche supérieure. Si vous n'effectuez pas de transition de overlay, votre élément est immédiatement découpé, transformé et masqué, et la transition ne se produit pas.

[open] {
  transition: opacity 1s, display 1s allow-discrete;
}

Incluez plutôt overlay dans la transition ou l'animation pour animer overlay avec le reste des éléments géographiques et vous assurer qu'il reste dans la couche supérieure lors de l'animation. L'aspect sera beaucoup plus fluide.

[open] {
  transition: opacity 1s, display 1s allow-discrete, overlay 1s allow-discrete;
}

En outre, lorsque plusieurs éléments sont ouverts dans la couche supérieure, la superposition vous aide à contrôler la transition en douceur vers et depuis la couche supérieure. Vous pouvez voir la différence dans cet exemple simple. Si vous n'appliquez pas overlay à la deuxième fenêtre pop-up lors de sa transition, elle sortira d'abord de la couche supérieure, sautant derrière l'autre fenêtre pop-up, avant de lancer la transition. L'effet n'est pas très fluide.

Remarque sur les transitions d'affichage

Si vous apportez des modifications DOM, par exemple en ajoutant et en supprimant des éléments, les transitions de vue constituent une solution idéale pour créer des animations fluides. Voici deux des exemples ci-dessus créés à l'aide de transitions de vue.

Dans cette première démonstration, au lieu de configurer @starting-style et d'autres transformations CSS, les transitions de vue géreront la transition. La transition de vue est configurée comme suit:

Tout d'abord, en CSS, attribuez un view-transition-name individuel à chaque fiche.

.card-1 {
  view-transition-name: card-1;
}

.card-2 {
  view-transition-name: card-2;
}

/* etc. */

Ensuite, en JavaScript, encapsulez la mutation DOM (dans ce cas, en supprimant la fiche) dans une transition de vue.

deleteBtn.addEventListener('click', () => {
  // Check for browser support
  if (document.startViewTransition) {
    document.startViewTransition(() => {
      // DOM mutation
      card.remove();
    });
  } 
  // Alternative if no browser support
  else {
    card.remove();
  }
})

Désormais, le navigateur peut gérer le fondu à la fermeture et le morphologie de chaque carte vers sa nouvelle position.

Autre exemple pratique : la démonstration d'ajout et de suppression d'éléments de liste. Dans ce cas, n'oubliez pas d'ajouter un view-transition-name unique pour chaque fiche créée.

Conclusion

Ces nouvelles fonctionnalités nous rapprochent de la fluidité des animations d'entrée et de sortie sur la plate-forme Web. Pour en savoir plus, consultez ces liens: