Niveau 21 — Les Transitions

Les Transitions

Donnez de la vie à vos interfaces avec des transitions CSS fluides. Apprenez à animer les changements de propriétés, maîtrisez les fonctions de timing et créez des effets visuels élégants.

1. Comprendre les Transitions

En une phrase : Une transition CSS permet d'animer progressivement le changement d'une propriété d'une valeur à une autre, sur une durée déterminée, avec une courbe de vitesse choisie.

Les transitions transforment des changements brusques en animations fluides. Au lieu qu'un bouton change instantanément de couleur au survol, la transition intercale des images intermédiaires sur la durée spécifiée.

Les 4 propriétés de transition

Propriété Description Exemple
transition-property Quelle(s) propriété(s) animer background, transform
transition-duration Combien de temps dure l'animation 0.3s, 300ms
transition-timing-function La courbe de vitesse ease, cubic-bezier()
transition-delay Délai avant le début 0.1s

Comment ça marche

CYCLE DE VIE D'UNE TRANSITION
═══════════════════════════════════════════════

   État initial          Animation          État final
   (hover: off)    →     (en cours)    →    (hover: on)
  ┌───────────┐       ┌───────────┐       ┌───────────┐
  │           │       │ ▓▓▓▓▓▓▓▓▓ │       │           │
  │  BLEU     │  ──→  │ ▓MIXTE▓▓▓ │  ──→  │  ROUGE    │
  │           │       │ ▓▓▓▓▓▓▓▓▓ │       │           │
  └───────────┘       └───────────┘       └───────────┘
       0%                50%                 100%

Déclencheurs :
  • :hover
  • :focus
  • :active
  • Classe ajoutée via JS
  • Changement de propriété via JS

Le navigateur intercale automatiquement les états intermédiaires

Quelles propriétés peuvent être transitionnées ?

Transitionnables Non transitionnables Attention (layout trigger)
color, background-color font-family width, height
transform, opacity display top, left, right, bottom
box-shadow visibility margin, padding
border-color, outline position border-width
font-size, line-height z-index grid-template-columns
text-shadow, filter overflow flex-basis
Performance : Pour des transitions fluides à 60fps, préférez toujours animer transform et opacity — elles sont accélérées par le GPU et ne déclenchent ni layout ni paint.

2. Syntaxe détaillée

2.1 transition-property

Définition : Spécifie quelles propriétés CSS doivent être animées lors du changement.
/* Toutes les propriétés transitionnables */
transition-property: all;

/* Une propriété spécifique */
transition-property: background-color;

/* Plusieurs propriétés */
transition-property: background-color, transform, opacity;

/* Aucune (désactive la transition) */
transition-property: none;

2.2 transition-duration

Définition : Définit la durée de l'animation en secondes (s) ou millisecondes (ms).
transition-duration: 0.3s;     /* 300 millisecondes */
transition-duration: 300ms;    /* Identique */
transition-duration: 0s;       /* Pas d'animation (défaut) */
transition-duration: 1.5s;     /* Animation lente */
Durée Impression Usage
0.1s – 0.2s Rapide, subtil Effets de focus, micro-interactions
0.2s – 0.3s Naturel, confortable Hover, toggle, couleur
0.3s – 0.5s Visible, lent Apparitions, slides, cartes
0.5s – 1s Lent, spectaculaire Animations de page, transitions majeures
> 1s Très lent Événements spéciaux, loading

2.3 transition-timing-function

Définition : Contrôle la vitesse de l'animation au fil du temps. C'est la courbe qui détermine si l'animation accélère, ralentit ou reste constante.

Les 5 courbes prédéfinies

ease

Défaut. Lent au début, rapide au milieu, ralentit à la fin.

linear

Vitesse constante du début à la fin.

ease-in

Lent au début, accélère. Idéal pour les départs.

ease-out

Rapide au début, ralentit. Idéal pour les arrivées.

ease-in-out

Lent début et fin, rapide au milieu.

cubic-bezier() — Courbes personnalisées

/* cubic-bezier(x1, y1, x2, y2) */
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);   /* Material Design */
transition-timing-function: cubic-bezier(0.25, 0.8, 0.25, 1); /* Apple-like */
transition-timing-function: cubic-bezier(0.68, -0.55, 0.27, 1.55); /* Élastique */
transition-timing-function: cubic-bezier(0.1, 0.7, 0.1, 1.0); /* Sortie douce */
COURBES CUBIC-BEZIER
═══════════════════════════════════════════════

  Vitesse                          cubic-bezier(x1, y1, x2, y2)
    ▲
    │        ╭────────── ease (0.25, 0.1, 0.25, 1.0)
    │      ╭─╯
    │    ╭─╯  ──── linear
    │  ╭─╯
    │╭─╯ ╭─────── ease-in-out
    │╯ ╭─╯
    │──╯───── ease-in
    │────────── ease-out
    └────────────────────────► Temps

  x1, y1 = point de contrôle 1 (début)
  x2, y2 = point de contrôle 2 (fin)

  Outils en ligne : cubic-bezier.com

Les courbes de timing et leur effet sur la vitesse

steps() — Animations par paliers

/* steps(nombre, direction) */
transition-timing-function: steps(5);          /* 5 pas, fin en last */
transition-timing-function: steps(5, start);   /* 5 pas, début en first */
transition-timing-function: steps(5, end);     /* 5 pas, fin en last (défaut) */

/* Exemple : compteur digital */
.compteur {
  transition: content 0.5s steps(10);
}

2.4 transition-delay

Définition : Définit le temps d'attente avant le début de l'animation.
transition-delay: 0s;       /* Pas de délai (défaut) */
transition-delay: 0.2s;     /* Attend 200ms avant de commencer */
transition-delay: 500ms;    /* Attend 500ms */

2.5 La shorthand

/* transition: property duration timing-function delay; */

/* Exemple complet */
.btn {
  transition: background-color 0.3s ease 0s,
              transform 0.2s ease 0.1s;
}

/* Shorthand pour tout */
.btn {
  transition: background-color 0.3s ease,
              transform 0.2s ease 0.1s;
}

/* Toutes les propriétés, même durée, même courbe */
.btn {
  transition: all 0.3s ease;
}

/* Valeur raccourcie avec 2 temps */
/* duration | delay */
.btn {
  transition: all 0.3s 0.1s;  /* 0.3s de durée, 0.1s de délai */
}

2.6 Comment une transition se déclenche

DÉCLENCHEURS DE TRANSITION
═══════════════════════════════════════════════

  1. :hover ──────── Survole de la souris
  2. :focus ──────── Focus clavier/clic
  3. :active ─────── Clic maintenu
  4. Classe ajoutée ─── JS: element.classList.add('active')
  5. Animation initiale ─── Au chargement de la page

  La transition se joue dans les DEUX sens :
  • Souris sur l'élément → état initial → état final
  • Souris quitte l'élément → état final → état initial
  (Retour toujours animé avec la même durée/courbe)

Les différents déclencheurs et le comportement aller-retour

3. Visualisation interactive

Effets de boutons au survol

Changement de couleur
Changement de taille
Ombre + déplacement
Soulignement glissant

Effets de cartes au survol

Soulèvement

Carte Soulèvement

Transform + shadow

Ombre croissante

Carte Ombre

Box-shadow uniquement

Zoom image
Image zoom

Carte Zoom

Transform: scale sur l'image

Navigation underline animée

Soulignement de lien au survol

Effets de focus sur inputs

Bordure animée
Glow au focus
Expansion

Toggle animé

Accordéon ouverture/fermeture

Une transition CSS anime progressivement le changement d'une propriété d'une valeur à une autre, sur une durée déterminée.

transform et opacity sont les plus performantes car elles sont accélérées par le GPU et ne déclenchent ni layout ni paint.

Pour les micro-interactions : 0.1-0.2s. Pour les hover : 0.2-0.3s. Pour les transitions visibles : 0.3-0.5s.

Menu glissant (slide-in)

Cliquez sur ☰ pour ouvrir le menu latéral

Fade in / Fade out

Fade in (survol)
Survol
Fade out (survol)
Survol

Scale, Rotate, Color Morph

Scale
Scale
Rotate
Rotate
Color Morph
Morph

will-change : hint de performance

Avec will-change: transform

GPU prêt

Sans will-change

Pas de hint GPU

prefers-reduced-motion

Hover

Réduction de mouvement

Si votre OS est en mode "réduire les animations", cette transition est désactivée.

4. Exemples progressifs

Exemple 1 : Transition de base (hover)

.bouton {
  background: #2563eb;
  color: white;
  border: none;
  padding: 0.75rem 1.5rem;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.3s ease;
}

.bouton:hover {
  background: #1d4ed8;
}

Exemple 2 : Multi-propriétés

.carte {
  background: white;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  transform: translateY(0);
  transition: transform 0.3s ease,
              box-shadow 0.3s ease;
}

.carte:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 20px rgba(0,0,0,0.15);
}

Exemple 3 : Transition avec délai

.menu-item {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}

/* Délai incrémental pour chaque item */
.menu-item:nth-child(1) { transition-delay: 0.05s; }
.menu-item:nth-child(2) { transition-delay: 0.10s; }
.menu-item:nth-child(3) { transition-delay: 0.15s; }
.menu-item:nth-child(4) { transition-delay: 0.20s; }

.menu.active .menu-item {
  opacity: 1;
  transform: translateY(0);
}

Exemple 4 : Soulignement animé

.lien {
  text-decoration: none;
  color: #2563eb;
  position: relative;
}

.lien::after {
  content: "";
  position: absolute;
  bottom: -2px;
  left: 0;
  width: 100%;
  height: 2px;
  background: #2563eb;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s ease;
}

.lien:hover::after {
  transform: scaleX(1);
}

Exemple 5 : Input focus glissant

.input {
  border: 2px solid #e2e8f0;
  border-radius: 8px;
  padding: 0.75rem 1rem;
  outline: none;
  transition: border-color 0.3s ease,
              box-shadow 0.3s ease;
}

.input:focus {
  border-color: #2563eb;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

Exemple 6 : Toggle switch

.toggle-track {
  width: 48px;
  height: 26px;
  background: #cbd5e1;
  border-radius: 13px;
  position: relative;
  cursor: pointer;
  transition: background 0.3s ease;
}

.toggle-track.active {
  background: #16a34a;
}

.toggle-thumb {
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  background: white;
  border-radius: 50%;
  box-shadow: 0 1px 3px rgba(0,0,0,0.2);
  transition: transform 0.3s ease;
}

.toggle-track.active .toggle-thumb {
  transform: translateX(22px);
}

5. Erreurs fréquentes

Erreur 1 : Animer des propriétés de layout
/* ❌ Lent — déclenche layout + paint */
.bloc {
  transition: width 0.3s ease,       /* Layout trigger */
              height 0.3s ease,       /* Layout trigger */
              margin 0.3s ease,       /* Layout trigger */
              top 0.3s ease,          /* Layout trigger */
              padding 0.3s ease;      /* Layout trigger */
}

/* ✅ Rapide — GPU accelerated */
.bloc {
  transition: transform 0.3s ease,   /* GPU ✓ */
              opacity 0.3s ease;      /* GPU ✓ */
}

/* Quand width/height sont indispensables, utiliser
   transform: scale() ou max-width à la place */
Erreur 2 : Utiliser all sans réfléchir
/* ❌ Transitionne TOUT, même les propriétés non voulues */
.btn {
  transition: all 0.3s ease;
}
/* Si un media query change le padding, ça anime aussi ! */

/* ✅ Cibler les propriétés spécifiques */
.btn {
  transition: background-color 0.3s ease,
              transform 0.2s ease;
}
Erreur 3 : Pas de retour au repos
/* ❌ Animation sur l'état hover mais pas au retour */
.btn:hover {
  transform: scale(1.1);
  /* Le retour est brutal car la transition est
     définie sur .btn, pas sur .btn:hover */
}

/* ✅ Définir la transition sur l'état de base */
.btn {
  transition: transform 0.3s ease;
}
.btn:hover {
  transform: scale(1.1);
}
Erreur 4 : Duration trop longue
/* ❌ L'utilisateur attend que l'animation finisse */
.btn {
  transition: all 1.5s ease;  /* Trop lent ! */
}

/* ✅ Rapide et confortable */
.btn {
  transition: background 0.2s ease;  /* Micro-interaction */
}
.carte {
  transition: transform 0.3s ease;  /* Effet hover */
}
Erreur 5 : Oublier prefers-reduced-motion
/* ❌ Pas d'alternative pour les utilisateurs sensibles */
.anime {
  animation: spin 2s linear infinite;
}

/* ✅ Toujours respecter la préférence */
@media (prefers-reduced-motion: reduce) {
  .anime {
    animation: none;
    transition: none;
  }
}
Erreur 6 : will-change mal utilisé
/* ❌ Mettre will-change sur tout */
.bloc {
  will-change: transform, opacity, width, height, color;
}

/* ✅ Utiliser uniquement sur les propriétés animées,
   et idéalement pendant la phase d'animation */
.bloc-animate {
  will-change: transform;
}
/* Retirer après l'animation si elle est ponctuelle */

6. Bonnes pratiques

Système de transitions cohérent :
/* Définir des tokens de transition */
:root {
  --transition-fast: 0.15s ease;
  --transition-base: 0.25s ease;
  --transition-slow: 0.4s ease;
  --transition-spring: 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Utiliser les tokens partout */
.btn {
  transition: background var(--transition-fast),
              transform var(--transition-base);
}

.carte {
  transition: transform var(--transition-base),
              box-shadow var(--transition-base);
}

.modal {
  transition: opacity var(--transition-slow),
              transform var(--transition-slow);
}
Propriétés performantes à privilégier :
  • 🚀 transform — GPU accelerated, ne déclenche pas le layout
  • 🚀 opacity — GPU accelerated, très léger
  • color, background-color — Paint uniquement
  • box-shadow, text-shadow — Paint uniquement
  • border-color, outline — Paint uniquement
  • 🐌 width, height, margin, padding — Layout trigger
  • 🐌 top, left, right, bottom — Layout trigger
Règles de durée :
  • ⏱️ Micro-interactions (couleur, opacity) → 0.15-0.2s
  • ⏱️ Hover effects (carte, bouton) → 0.2-0.3s
  • ⏱️ Entrées (modal, slide-in) → 0.3-0.5s
  • ⏱️ Transitions majeures (page, section) → 0.5-1s
  • ⏱️ Plus de 1s → uniquement pour des effets spéciaux
Patterns de transition populaires :
/* Soulèvement de carte */
.carte:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 20px rgba(0,0,0,0.12);
}

/* Soulignement de lien */
.lien::after {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s ease;
}
.lien:hover::after { transform: scaleX(1); }

/* Scale au focus */
.input:focus {
  transform: scale(1.02);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}

/* Fade + slide au survol */
.overlay {
  opacity: 0;
  transform: translateY(10px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.carte:hover .overlay {
  opacity: 1;
  transform: translateY(0);
}

7. Mini-défi

Défi 1 : Bouton avec 3 effets

Créez un bouton qui change de couleur, d'ombre et de taille au survol, avec des durées différentes pour chaque propriété.

.bouton {
  background: #2563eb;
  color: white;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background-color 0.2s ease,
              box-shadow 0.3s ease 0.05s,
              transform 0.15s ease;
}

.bouton:hover {
  background: #1d4ed8;
  box-shadow: 0 8px 20px rgba(37, 99, 235, 0.3);
  transform: translateY(-2px);
}

Défi 2 : Card avec overlay au survol

Créez une carte image qui révèle une couche noire semi-transparente avec titre et description au survol.

Défi 3 : Input focus animé

Créez un champ de formulaire avec une bordure qui change de couleur et un glow au focus, le tout avec une transition fluide.

Défi 4 : Menu hamburger animé

Créez un bouton hamburger (3 barres) qui se transforme en X au clic avec une animation fluide.

.hamburger {
  width: 30px;
  height: 20px;
  position: relative;
  cursor: pointer;
}

.hamburger span {
  display: block;
  width: 100%;
  height: 3px;
  background: #1e293b;
  position: absolute;
  transition: transform 0.3s ease, opacity 0.2s ease;
}

.hamburger span:nth-child(1) { top: 0; }
.hamburger span:nth-child(2) { top: 8px; }
.hamburger span:nth-child(3) { top: 16px; }

.hamburger.active span:nth-child(1) {
  transform: rotate(45deg) translate(5px, 6px);
}
.hamburger.active span:nth-child(2) {
  opacity: 0;
}
.hamburger.active span:nth-child(3) {
  transform: rotate(-45deg) translate(5px, -6px);
}

Défi 5 : Accéibilité

Ajoutez prefers-reduced-motion à un de vos effets de transition pour qu'il soit désactivé pour les utilisateurs sensibles au mouvement.

8. Projets pratiques

Projet 1 : Galerie avec effets hover

Créez une galerie de cartes avec :

  • Soulèvement au survol (transform + shadow)
  • Overlay qui apparaît avec titre et description
  • Transition de l'image (zoom subtil)
  • Délai incrémental entre les cartes
  • Respect de prefers-reduced-motion

Projet 2 : Menu de navigation animé

Créez un menu complet avec :

  • Soulignement animé au survol des liens
  • Sous-menus qui se déploquent avec transition
  • Bouton hamburger qui s'anime en X
  • Menu mobile glissant (slide-in)
  • Timing fluide et professionnel

Projet 3 : Formulaire interactif

Créez un formulaire avec :

  • Inputs avec focus glow animé
  • Labels qui se déplacent au focus
  • Toggle switches pour les options
  • Bouton submit avec états (normal, hover, loading)
  • Messages d'erreur avec fade-in

Projet 4 : Modal avec transitions

Créez une modale avec :

  • Overlay fade-in
  • Contenu modal scale + slide-in
  • Bouton de fermeture animé
  • Fermeture au clic sur l'overlay
  • Trap de focus accessible

9. Révision

Récapitulatif des concepts clés

Concept Propriété Valeurs
Propriété animée transition-property all, none, nom de propriété
Durée transition-duration 0.3s, 300ms
Courbe transition-timing-function ease, linear, cubic-bezier(), steps()
Délai transition-delay 0.1s, 100ms
Shorthand transition property duration timing delay

Quiz rapide

  1. Quelles sont les 4 propriétés de transition ?
  2. Quelle est la durée recommandée pour un hover de bouton ?
  3. Quelle propriété CSS permet une courbe de timing personnalisée ?
  4. Quelles propriétés sont accélérées par le GPU ?
  5. Qu'est-ce que transition: all 0.3s ease fait ?
  6. Pourquoi faut-il éviter d'animer width et height ?
  7. Comment créer un délai entre plusieurs éléments ?
  8. Quelle est la différence entre ease et ease-in-out ?
  9. Comment désactiver les transitions pour les utilisateurs sensibles ?
  10. Qu'est-ce que will-change fait ?
Réponses :
  1. transition-property, transition-duration, transition-timing-function, transition-delay
  2. 0.2s à 0.3s
  3. cubic-bezier()
  4. transform et opacity
  5. Anime toutes les propriétés transitionnables pendant 0.3s avec la courbe ease
  6. Ils déclenchent le layout (reflow), ce qui est coûteux en performance
  7. Avec transition-delay pour chaque élément (incrémental)
  8. ease est la courbe par défaut ; ease-in-out est symétrique (lent début et fin)
  9. Avec @media (prefers-reduced-motion: reduce)
  10. Il indique au navigateur de préparer l'accélération GPU d'une propriété

Cheat sheet rapide

/* Transition basique */
transition: property 0.3s ease;

/* Multi-propriétés */
transition: background-color 0.2s ease,
            transform 0.3s ease 0.1s,
            box-shadow 0.3s ease;

/* Tokens */
:root {
  --t-fast: 0.15s ease;
  --t-base: 0.25s ease;
  --t-slow: 0.4s ease;
}

/* Performance — toujours préférer */
transition: transform 0.3s ease,  /* GPU ✓ */
            opacity 0.3s ease;     /* GPU ✓ */

/* Anti-pattern — à éviter */
transition: width 0.3s ease,      /* Layout ✗ */
            margin 0.3s ease;     /* Layout ✗ */

/* Accéleré par le GPU */
transition: transform 0.3s ease;
transition: opacity 0.3s ease;

/* will-change (utiliser avec parcimonie) */
.anime { will-change: transform; }

/* prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; }
}

/* Soulignement de lien */
.lien::after {
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s ease;
}
.lien:hover::after { transform: scaleX(1); }

/* Soulèvement de carte */
.carte {
  transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.carte:hover {
  transform: translateY(-4px);
  box-shadow: 0 8px 20px rgba(0,0,0,0.12);
}

/* Focus glow */
.input:focus {
  outline: none;
  border-color: #2563eb;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.15);
}