iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
iducationducation
IndexArticlesFormationsProfilOutilsBibliothech
N°014 — 2026
Navigation
01Index02Articles03Formations04Profil05Outils06Bibliothech
N°014 — 2026
Formations
JavaScript · Intermédiaire

GSAP

Maîtriser GSAP de zéro : tweens, timelines, ScrollTrigger, plugins et intégration React/Next.js pour créer des animations web professionnelles.

GSAPJavaScriptReactNext.jsScrollTrigger
01Introduction à GSAP02Tweens : to, from, fromTo03Timelines04ScrollTrigger05Stagger, utils et matchMedia06GSAP dans React et Next.js07Plugins et techniques avancées
Chapitre 3·25 min

Timelines

Dès qu'on veut enchaîner plusieurs animations, les tweens individuels avec des delay calculés à la main deviennent un cauchemar. Changer la durée d'une animation force à recalculer tous les délais suivants.

// À éviter — delay manuel = fragile
gsap.from('.title', { y: 30, opacity: 0, duration: 0.8 })
gsap.from('.subtitle', { y: 20, opacity: 0, duration: 0.6, delay: 0.8 })
gsap.from('.button', { scale: 0.9, opacity: 0, duration: 0.5, delay: 1.4 })

Changer la durée du .title casse tout. Les timelines résolvent ça.

Créer une timeline

const tl = gsap.timeline()
 
tl.from('.title', { y: 30, opacity: 0, duration: 0.8 })
  .from('.subtitle', { y: 20, opacity: 0, duration: 0.6 })
  .from('.button', { scale: 0.9, opacity: 0, duration: 0.5 })

Par défaut, chaque animation s'enchaîne après la précédente. La timeline calcule le timing automatiquement. Changer la durée de .title décale tout le reste proportionnellement.

Le paramètre de position

Le troisième argument d'une animation dans une timeline est la position — quand elle démarre dans la timeline.

const tl = gsap.timeline()
 
// Démarre à 1.5s dans la timeline
tl.from('.element', { opacity: 0, duration: 1 }, 1.5)
 
// Démarre 0.2s après la fin de l'animation précédente (décalage positif)
tl.from('.element', { opacity: 0, duration: 1 }, '+=0.2')
 
// Démarre 0.2s AVANT la fin de l'animation précédente (overlap)
tl.from('.element', { opacity: 0, duration: 1 }, '-=0.2')
 
// Démarre en même temps que l'animation précédente
tl.from('.element', { opacity: 0, duration: 1 }, '<')
 
// Démarre 0.3s après le DÉBUT de l'animation précédente
tl.from('.element', { opacity: 0, duration: 1 }, '<0.3')
 
// Démarre au début de la timeline
tl.from('.element', { opacity: 0, duration: 1 }, 0)

Le < est particulièrement utile pour des animations en parallèle avec un léger décalage.

Exemple concret : animation d'une carte

const tl = gsap.timeline()
 
tl
  .from('.card', { y: 60, opacity: 0, duration: 0.7, ease: 'power3.out' })
  .from('.card-image', { scale: 1.1, duration: 0.6, ease: 'power2.out' }, '<')  // en même temps
  .from('.card-title', { y: 15, opacity: 0, duration: 0.5 }, '-=0.2')           // overlap
  .from('.card-body', { y: 10, opacity: 0, duration: 0.4 }, '-=0.2')
  .from('.card-button', { scale: 0.9, opacity: 0, duration: 0.3 }, '-=0.1')

Labels

Les labels permettent de nommer des points dans la timeline.

const tl = gsap.timeline()
 
tl
  .from('.hero', { opacity: 0, duration: 1 })
  .addLabel('heroVisible')
  .from('.nav', { y: -30, duration: 0.5 })
  .addLabel('navIn')
  .from('.content', { y: 40, opacity: 0, duration: 0.8 })
 
// Sauter à un label
tl.play('heroVisible')
tl.seek('navIn')

Utile pour des animations longues (landing pages) où on veut pouvoir reprendre à un point précis.

Options de la timeline

const tl = gsap.timeline({
  // Defaults pour toutes les animations de cette timeline
  defaults: {
    duration: 0.6,
    ease: 'power2.out',
  },
 
  // Répétition
  repeat: 2,
  yoyo: true,
  repeatDelay: 0.5,
 
  // Callbacks
  onStart: () => console.log('début'),
  onComplete: () => console.log('fin'),
  onRepeat: () => console.log('répétition'),
 
  // Ne démarre pas immédiatement
  paused: true,
})

defaults sur une timeline évite de répéter duration et ease sur chaque animation :

const tl = gsap.timeline({
  defaults: { duration: 0.7, ease: 'power3.out' },
})
 
// Ces animations héritent de duration: 0.7 et ease: 'power3.out'
tl
  .from('.title', { y: 30, opacity: 0 })
  .from('.text', { y: 20, opacity: 0 })
  .from('.cta', { scale: 0.9, opacity: 0 })

Contrôle de lecture

Une timeline expose les mêmes contrôles qu'un tween.

const tl = gsap.timeline({ paused: true })
tl.from('.menu-items', { x: -20, opacity: 0, stagger: 0.08 })
 
// Déclenchement
document.querySelector('.menu-toggle').addEventListener('click', () => {
  if (tl.reversed()) {
    tl.play()
  } else {
    tl.reverse()
  }
})

.reversed() retourne true si la timeline joue en sens inverse. Ce pattern — play/reverse sur une même timeline — est la façon propre de gérer des animations d'ouverture/fermeture (menus, modales, accordéons).

Timelines imbriquées

Une timeline peut contenir d'autres timelines. Ça permet d'isoler des animations réutilisables.

function createCardAnimation(card) {
  const tl = gsap.timeline()
  tl
    .from(card, { y: 40, opacity: 0, duration: 0.6 })
    .from(card.querySelector('.title'), { y: 10, opacity: 0, duration: 0.4 }, '-=0.2')
  return tl
}
 
// Timeline principale qui orchestre les cartes
const mainTl = gsap.timeline()
document.querySelectorAll('.card').forEach((card) => {
  mainTl.add(createCardAnimation(card), '-=0.3')
})

Chaque carte a sa propre timeline de 600ms + 400ms, mais elles se chevauchent de 300ms dans la timeline principale — effet cascade fluide.

kill() et cleanup

Toujours tuer les tweens et timelines qui ne sont plus nécessaires — sinon les animations continuent sur des éléments qui n'existent plus dans le DOM.

const tl = gsap.timeline()
// ... animations
 
// Arrêter et libérer
tl.kill()
 
// Tuer toutes les animations sur un élément
gsap.killTweensOf('.element')
 
// Tuer toutes les animations GSAP de la page
gsap.globalTimeline.clear()

Ce cleanup est particulièrement important en React et dans les SPAs — c'est couvert en détail au chapitre 6.


Tweens et timelines donnent un contrôle complet sur des animations séquencées. La suite : ScrollTrigger — le plugin qui lie vos animations à la position de scroll de l'utilisateur.

Précédent
Tweens : to, from, fromTo
Suivant
ScrollTrigger

Développeur fullstack passionné. J'apprends en construisant et je documente tout — front, back, outils. Le code s'apprend mieux en public.

Naviguer

IndexTous les articlesFormationsProfilOutilsBibliothech

Ailleurs

GitHub RSS

Newsletter

Les articles, libs et découvertes. Une fois par semaine, pas plus.

© 2026 William LoreeConçu & codé à la main