Essayer de coder ← Retour aux sujets

Transitions et transform

transition

Une transition anime le passage d'un état à un autre (survol, ajout d'une classe) sans JavaScript. On la déclare sur l'état de départ.

transition: transform 0.25s ease;
Propriété animée + durée + courbe
transition: all 0.3s;
Toutes les propriétés : pratique mais à éviter (coûteux)
transition-delay: 0.1s;
Attente avant le départ
.btn:hover { transform: scale(1.05); }
L'état d'arrivée, au survol
transform: translateY(-4px) rotate(2deg);
Décaler, tourner, agrandir sans toucher à la mise en page
opacity: 0.6;
Transparence (animable)
bouton.css
.btn {
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgb(0 0 0 / 20%);
}
Rendu
Au survol, le bouton monte de 2 pixels et son ombre s'agrandit, en 0,2 seconde.

Animations avec @keyframes

@keyframes

Une animation déroule une séquence d'étapes décrite dans @keyframes. Elle démarre d'elle-même et peut tourner en boucle.

@keyframes pulse { 50% { transform: scale(1.1); } }
Les étapes (en pourcentage, ou from et to)
animation: pulse 1.5s ease-in-out infinite;
Nom, durée, courbe, répétitions
animation-iteration-count: 3;
Nombre de répétitions (infinite : sans fin)
animation-direction: alternate;
Un coup dans un sens, un coup dans l'autre
animation-fill-mode: forwards;
Reste dans l'état final à la fin
animation-play-state: paused;
Met l'animation en pause
apparition.css
@keyframes apparition {
  from {
    opacity: 0;
    transform: translateY(8px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.carte {
  animation: apparition 0.4s ease-out both;
}
Rendu
Chaque carte apparaît en fondu en glissant de 8 pixels vers le haut.

✨ Le cours : donner vie à l'interface

Une animation bien dosée guide le regard (un bouton qui réagit, un élément qui apparaît en douceur) ; mal dosée, elle fatigue, ralentit la page et peut même rendre malade. Cette fiche couvre les transitions, les transformations et les animations, avec leurs bonnes pratiques.

Transition ou animation ?

TransitionAnimation (@keyframes)
principepasser d'un état A à un état Bdérouler une séquence d'étapes
déclenchementun changement : survol, focus, ajout d'une classetout seul au chargement, ou quand la classe est ajoutée
étapesdeux (départ, arrivée)autant qu'on veut (0 %, 40 %, 100 %…)
répétitionnonoui (animation-iteration-count)
à utiliser pourretours visuels (boutons, menus)chargements, entrées en scène, effets en boucle

Les propriétés d'une transition

transition: propriété durée courbe délai. On peut animer plusieurs propriétés avec des durées différentes en les séparant par des virgules. La transition se déclare sur l'élément dans son état de départ : ainsi elle joue aussi au retour (quand le survol cesse).

PropriétéRôleExemple
transition-propertyce qui s'animetransform, opacity, background-color
transition-durationdurée0.25s (250 ms)
transition-timing-functionaccélérationease, linear, ease-in, ease-out, ease-in-out, cubic-bezier(…), steps(4)
transition-delayattente avant le départ0.1s

transform : déplacer, tourner, agrandir

transform modifie le dessin d'un élément sans changer la place qu'il occupe dans la page (les voisins ne bougent pas). Ses fonctions : translate(x, y), scale(n), rotate(45deg), skew(…). On peut les combiner en une seule déclaration (elles s'appliquent dans l'ordre) ; transform-origin déplace le point autour duquel on tourne ou on agrandit.

transform.css
.carte:hover {
  transform: translateY(-4px) rotate(-1deg) scale(1.02);
}

.aiguille {
  transform-origin: left center;    /* tourne autour de son extrémité gauche */
  transform: rotate(45deg);
}

@keyframes : décrire une séquence

On nomme la séquence puis on l'applique avec animation. Les étapes se donnent en pourcentage de la durée (0%, 50%, 100%) ou avec from et to. Ci-dessous, un indicateur de chargement : un cercle gris dont la partie haute est colorée, qui tourne en continu à vitesse constante (linear).

chargement.css
@keyframes tourne {
  to {
    transform: rotate(360deg);
  }
}

.chargement {
  width: 40px;
  height: 40px;
  border: 4px solid #cbd5e1;
  border-top-color: #2563eb;
  border-radius: 50%;
  animation: tourne 0.8s linear infinite;
}
Rendu
Un cercle gris dont un quart est bleu, qui tourne sans fin.

Les propriétés d'animation

PropriétéValeurs usuelles
animation-namele nom donné dans @keyframes
animation-duration0.4s, 1.5s
animation-timing-functioncomme pour les transitions
animation-delayattente avant le départ (une valeur négative démarre « en cours de route »)
animation-iteration-count1, 3, infinite
animation-directionnormal, reverse, alternate (aller-retour)
animation-fill-modeforwards garde l'état final ; backwards applique l'état initial pendant le délai ; both les deux
animation-play-staterunning ou paused
pulse.css
@keyframes pulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
}

.badge {
  animation: pulse 1.5s ease-in-out infinite;
}

Animer sans ralentir la page

Pour chaque image, le navigateur calcule la mise en page, dessine, puis compose les calques. Animer width, height, top, left ou margin oblige à recalculer toute la mise en page à chaque image : saccades assurées sur un téléphone modeste. transform et opacity sont gérés directement par la carte graphique, sans recalcul : anime-les en priorité. Pour déplacer un élément, préfère translate à left. will-change: transform prévient le navigateur qu'un élément va bouger, mais à utiliser avec parcimonie.

Déclencher une transition avec JavaScript

Un script n'a pas besoin d'animer lui-même : il ajoute ou retire une classe, et la transition CSS fait le reste.

menu.css
.menu {
  transform: translateX(-100%);
  transition: transform 0.3s ease;
}

.menu.ouvert {
  transform: translateX(0);
}
menu.js
document.querySelector("#bouton").addEventListener("click", () => {
  document.querySelector(".menu").classList.toggle("ouvert");
});

Respecter les personnes sensibles au mouvement

Certaines personnes (troubles vestibulaires, migraines, épilepsie photosensible) peuvent être gênées voire malades à cause des animations. Elles le disent à leur système, et ton CSS peut le lire avec prefers-reduced-motion. Voici une règle de sécurité courante (un des rares cas où !important est justifié) :

mouvement-reduit.css
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

Évite aussi les effets qui clignotent plus de trois fois par seconde, et donne le moyen d'arrêter tout contenu qui bouge en continu (voir Accessibilité).

⚠️ Erreurs fréquentes

Mettre la transition sur l'état d'arrivée

À éviter
faux.css
.btn:hover {
  transform: scale(1.1);
  transition: transform 0.3s;   /* joue à l'aller seulement */
}
Correct
correct.css
.btn {
  transition: transform 0.3s;   /* joue à l'aller ET au retour */
}
.btn:hover {
  transform: scale(1.1);
}

Animer une propriété qui ne s'anime pas

display (de none à block) ne s'anime pas, ni height: auto. Anime plutôt opacity et transform, ou une hauteur en valeur chiffrée (max-height).

Écraser une transformation par une autre

transform: rotate(10deg); puis plus loin transform: scale(1.2); : la seconde remplace la première. Écris-les ensemble : transform: rotate(10deg) scale(1.2);.

L'animation qui revient au départ à la fin

Une animation terminée rend l'élément à son état normal. Si l'état final doit rester (un élément qui apparaît), ajoute animation-fill-mode: forwards (ou both dans le raccourci).

Des durées trop longues

Pour la réponse à une action (survol, clic), reste entre 150 et 300 ms. Une interface qui fait attendre ne semble pas élégante, mais lente.

Des animations infinies sans raison

Un élément qui bouge en permanence attire l'œil en continu et empêche de lire. Réserve les boucles aux indicateurs de chargement, et prévois toujours prefers-reduced-motion.

📋 Aide-mémoire

  • transition: propriété durée courbe délai; sur l'état de départ ; changement d'état = :hover, :focus-visible, classe ajoutée.
  • transform : translate, scale, rotate, skew en une seule déclaration ; transform-origin pour le pivot.
  • @keyframes nom { from {…} to {…} } (ou 0%, 50%, 100%) puis animation: nom 1s ease infinite;.
  • animation-fill-mode: forwards garde l'état final ; alternate fait l'aller-retour ; paused met en pause.
  • Anime transform et opacity (rapides), évite width, height, top, left.
  • @media (prefers-reduced-motion: reduce) pour désactiver les mouvements ; JavaScript ajoute une classe, le CSS anime.