frontend / css
Transitions et animations
Explication
Ce que vous allez apprendre
- Distinguer clairement
transition(un changement entre deux états) et@keyframes/animation(une séquence autonome) - Éviter le piège de performance de
transition: allen listant explicitement les propriétés animées - Contrôler la vitesse perçue d'une animation avec les fonctions de timing (
ease,cubic-bezier, etc.) - Empêcher le "flash" de retour à l'état initial grâce à
animation-fill-mode - Créer un effet de cascade sur une liste d'éléments avec
animation-delay - Piloter la lecture d'une animation en JavaScript via
animation-play-state
Dans quel contexte ?
Une équipe travaille sur le tableau de bord d'une application de gestion de commandes. Quand un utilisateur clique sur "Valider la commande", le bouton doit changer de couleur en douceur (une transition), pendant qu'une icône de succès pulse doucement pour attirer l'œil (une animation en boucle). Sans ces deux outils bien maîtrisés, l'interface paraît soit figée et brutale, soit distrayante et mal maîtrisée côté performance.
Étape 1 : le mouvement aide à comprendre
Une interface qui change d'état brutalement est plus difficile à suivre pour l'œil qu'une transition fluide. L'animation CSS n'est donc pas qu'un effet décoratif : elle aide l'utilisateur à comprendre CE QUI a changé.
Étape 2 : deux outils, une confusion fréquente
Il existe une confusion classique entre transition et @keyframes/animation. Une transition anime le passage entre DEUX états déclenchés par un événement, comme :hover — elle a besoin d'un changement pour se déclencher.
| Outil | Déclenchement | Cas d'usage typique |
|---|---|---|
transition | un changement d'état (:hover, ajout d'une classe) | survol de bouton, ouverture d'un menu |
@keyframes + animation | autonome, dès l'application de la règle | spinner de chargement, pulsation de badge |
Étape 3 : et pour une séquence autonome ?
Une animation basée sur @keyframes définit, elle, une séquence AUTONOME avec plusieurs étapes intermédiaires, capable de se lancer d'elle-même sans attendre d'interaction — un chargement en boucle, une pulsation de notification.
Étape 4 : le piège de transition: all
Une fois cette distinction claire, voici un piège courant : transition: all 0.3s semble pratique, mais force le navigateur à surveiller CHAQUE propriété CSS en continu.
Piège fréquent
transition: all peut animer des propriétés que vous n'aviez pas prévues (par exemple une height qui change à cause d'un contenu dynamique), créant des effets visuels inattendus. Listez toujours les propriétés explicitement : transition: background 0.3s, transform 0.3s.
Étape 5 : pourquoi c'est un problème en pratique
Cela consomme plus de ressources qu'une liste explicite, et peut créer des animations non désirées sur des propriétés qu'on ne pensait pas concernées. Lister précisément les propriétés animées reste la bonne pratique.
Étape 6 : le flash désagréable après une animation
Il reste un dernier piège très fréquent : sans précaution, une animation revient à son état de départ dès qu'elle se termine, créant un flash visuel disgracieux.
La solution à ce flash
Bonne pratique
Ajoutez toujours animation-fill-mode: forwards (ou both) sur une animation d'apparition : sans cela, l'élément redevient invisible une fraction de seconde après la fin de l'animation, ce qui donne une impression de bug.
animation-fill-mode: forwards (ou both) corrige ce comportement en conservant l'état final de l'animation une fois celle-ci terminée.
Et ensuite ?
Une fois transitions et animations maîtrisées, la prochaine étape ajoute une dimension supplémentaire : les transformations 2D et 3D.
Commandes & code
Transitions et animations
Animer des changements d'état simples avec transition, des séquences complexes avec @keyframes.
/* transition : anime un changement de valeur entre deux états */
.bouton {
background: #2563eb;
transform: scale(1);
transition: background 0.2s ease, transform 0.15s ease-out;
}
.bouton:hover {
background: #1d4ed8;
transform: scale(1.03);
}
/* transition: all -> pratique mais coûteux (surveille TOUTES les propriétés,
y compris celles qu'on ne voulait pas animer) : à éviter en production */
.mauvais { transition: all 0.3s; }
.bon { transition: background 0.3s, transform 0.3s; }
/* Fonctions de timing */
.rapide-au-debut { transition-timing-function: ease-out; }
.rapide-a-la-fin { transition-timing-function: ease-in; }
.symetrique { transition-timing-function: ease-in-out; }
.lineaire { transition-timing-function: linear; }
.personnalise { transition-timing-function: cubic-bezier(0.34, 1.56, 0.64, 1); } /* effet "rebond" *//* @keyframes : séquence à plusieurs étapes, indépendante d'un état déclenché */
@keyframes apparition {
from {
opacity: 0;
transform: translateY(12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes pulsation {
0% { transform: scale(1); }
50% { transform: scale(1.08); }
100% { transform: scale(1); }
}
.carte {
animation: apparition 0.4s ease-out both;
/* both : applique le style du 1er keyframe avant le début,
et garde celui du dernier après la fin */
}
.badge-notification {
animation: pulsation 1.5s ease-in-out infinite;
}
/* Décalage en cascade pour une liste d'éléments */
.liste li {
animation: apparition 0.4s ease-out both;
}
.liste li:nth-child(1) { animation-delay: 0.05s; }
.liste li:nth-child(2) { animation-delay: 0.1s; }
.liste li:nth-child(3) { animation-delay: 0.15s; }/* Contrôle fin d'une animation */
.element {
animation-name: pulsation;
animation-duration: 2s;
animation-timing-function: ease-in-out;
animation-delay: 0.5s;
animation-iteration-count: 3; /* ou "infinite" */
animation-direction: alternate; /* aller-retour à chaque itération */
animation-fill-mode: forwards; /* garde l'état final après la fin */
animation-play-state: paused; /* pilotable en JS, ex: au survol */
}
.element:hover {
animation-play-state: running;
}Résumé
transitionanime un changement d'état ;@keyframes+animationanime une séquence autonome.- Lister explicitement les propriétés animées (jamais
transition: all) pour la lisibilité et la performance. animation-fill-mode: both/forwardsévite le "flash" de retour à l'état initial après une animation.animation-delaydécalé par élément crée un effet de cascade sans JavaScript.
Exercices pratiques
Mission : un badge de succès qui clignote et disparaît trop tôt
Objectif : Corriger un usage risqué de transition: all et un flash de fin d'animation sur un badge de validation de commande.
Contexte
Sur commande.css, le bouton .btn-valider utilise transition: all 0.3s; pour animer sa couleur au survol. Une fois la commande validée, un badge .badge-succes reçoit dynamiquement la classe .apparait, qui déclenche animation: apparition 0.4s ease-out; (sans autre réglage d'animation). Deux bugs sont observés : la hauteur du bouton "saute" visiblement pendant le survol à cause d'un changement de padding lié au JS, et le badge de succès clignote en redevenant invisible juste après son apparition.