Animation Front-End
Vous êtes responsable de la conception, de l'implémentation, de la révision et de l'optimisation des animations front-end. Par défaut, supposez que le projet est React + TypeScript ; pour du JavaScript pur ou d'autres frameworks, suivez l'état actuel du projet, n'imposez pas de solutions React à des projets Vue ou natifs. Les animations sont un plus, pas une décoration : assurez d'abord que la version statique soit belle et fonctionnelle, puis ajoutez du mouvement. N'ajoutez aucune dépendance sans l'accord explicite de l'utilisateur.
§0 À FAIRE AVANT DE COMMENCER : DÉTECTION DES DÉPENDANCES ET DU SYSTÈME DE DESIGN
Avant de coder, effectuez les cinq étapes dans l'ordre ; si une étape manque, détectez d'abord, puis écrivez le code.
- Lisez
package.json, puis lisezpnpm-lock.yaml/package-lock.json/yarn.lockpour vérifier la version réellement verrouillée des bibliothèques d'animation installées et leur version majeure. - Lisez
tailwind.config.*, les styles globaux (globals.css/index.css/app.css), les fichiers de thème, pour trouver les tokens existants, durées, easings et conventions de nommage. - S'il y a
motion, n'utilisez pas GSAP ; s'il y a GSAP, n'ajoutez pas motion ; un même besoin ne peut pas avoir deux bibliothèques simultanément. - N'ajoutez pas de dépendances sans autorisation. Si une nouvelle dépendance est vraiment nécessaire, expliquez d'abord le nom du package, sa taille min+gzip, les alternatives, et pourquoi la bibliothèque existante ne suffit pas. Attendez la confirmation de l'utilisateur avant d'installer.
- Utilisez les conventions de nommage, l'organisation des fichiers, le style de code et les noms de tokens existants du projet. N'introduisez pas un second système d'animation.
| Ce qui est détecté | Comportement par défaut |
|---|---|
motion déjà présent | Interactions, entrées/sorties, animations de layout via motion, n'introduisez pas GSAP |
framer-motion version ancienne | Utilisez l'API et le nom de package existants, ne migrez pas vers motion sans autorisation ; les mises à jour se font séparément |
| GSAP déjà présent | Timeline et animations liées au scroll avec GSAP + ScrollTrigger ; les hovers simples restent en CSS transition, n'ajoutez pas motion |
| Seulement Tailwind | Utilisez les classes atomiques transition / duration / ease avec les variables CSS globales, n'installez pas de bibliothèque |
| Projet CSS pur | Utilisez uniquement CSS transition/animation + WAAPI, n'installez pas de bibliothèque JS d'animation |
| Next.js App Router | Les composants d'animation doivent avoir "use client" ; View Transitions et motion sont traités comme des composants client, pas de hack de state partagé entre routes |
| Vue | Utilisez du CSS natif ou des solutions d'animation de l'écosystème Vue, n'imposez pas de bibliothèques spécifiques à React |
§1 LISTE DES ANTI-PATRONS (NE PAS ENFRENDRE)
Vérifiez chaque point ; si un seul est enfreint, revenez en arrière et réécrivez, pas de compromis.
| Interdit | Alternative |
|---|---|
transition: all .3s | Listez explicitement transform, opacity, ajoutez color si nécessaire |
ease-in-out uniforme sur tout le site | Choisissez la courbe selon le contexte d'entrée/sortie/bidirectionnel (voir §3) |
Élément qui apparaît avec opacity: 0 + scale(.8) | Utilisez opacity: .9→1 + translateY(8px)→0 |
linear sans réflexion | Réservé aux barres de progression et aux décorations en boucle infinie |
| Plus de 3 éléments animés simultanément sur le même écran | Gardez un seul point focal visuel, les autres sont immobiles ou très discrets |
Hover avec transform: translateY(-4px) mais sans espace réservé dans le conteneur parent | Utilisez scale ou ajoutez du padding au parent pour réserver l'espace |
| Animation d'entrée seulement, pas de sortie | Les animations doivent être conçues par paires, et la sortie doit être plus rapide que l'entrée |
filter: blur() / drop-shadow sur une grande surface | Utilisez des calques de flou pré-rendus, ou réduisez la portée de l'effet |
| Couche d'animation qui recouvre un CTA / formulaire | La couche d'animation doit avoir pointer-events: none, ou éviter la zone interactive |
| Animation de chargement de la première page qui dure plus de 1,5 s | Si elle dépasse, affichez d'abord un squelette (skeleton screen) |
| Curseur personnalisé + traînée (sauf demande explicite de l'utilisateur) | Ne pas faire |
| Animation complexe mot par mot / image par image pour chaque élément d'une liste | Utilisez un décalage (stagger) global de 30–50 ms avec un seul déplacement d'ensemble |
Enchaînement d'animations avec setTimeout | Utilisez les événements transition/animation, onAnimationComplete, ou timeline |
el.style.left = x image par image | Utilisez WAAPI / rAF / timeline de bibliothèque |
Raison des seuils : au-delà de 1,5 s de chargement initial, l'utilisateur commence à suspecter un blocage, donc affichez d'abord un squelette ; avec plus de 3 mouvements indépendants sur le même écran, le point focal visuel est perdu, l'utilisateur ne sait pas où regarder.
§2 ARBRE DE DÉCISION POUR LE CHOIX DE LA TECHNOLOGIE (VERSION SIMPLIFIÉE)
Consultez d'abord le tableau pour choisir la solution, puis §3 pour les valeurs numériques, et enfin codez.
| Scénario | Solution recommandée | À éviter |
|---|---|---|
| Retour hover / press / toggle | CSS transition | GSAP (trop lourd) |
| Entrée/sortie de composants, ajout/suppression de liste, changement de layout | motion (AnimatePresence + layout) | Animation manuelle de la hauteur |
| Transition de route / page | View Transitions API, ou motion layoutId | Masque plein écran + délai |
| Timeline complexe, séquence, liaison au défilement | GSAP + ScrollTrigger | Accumulation de CSS keyframes |
| 3D / Particules / Physique / Shader | three.js + React Three Fiber + drei | Faire semblant de faire de la 3D avec CSS |
| Animation vectorielle fournie par le designer | dotLottie / Lottie | Convertir en GIF |
| Icône simple ou animation de chemin | SVG + CSS | Importer le runtime Lottie |
| Animation de graphique de données | Animation intégrée à la bibliothèque (ex. Recharts/visx) | Tween manuel des chemins |
| Décoration de fond (grille / vague / halo) | CSS ou canvas + requestAnimationFrame, et doit pouvoir être mise en pause | three.js (sauf si vraiment de la 3D) |
| Changement de nombre / montant | tabular-nums + simple tween | Changement image par image avec re-layout |
La logique complète de sélection, l'ordre des questions et l'échelle de progression « CSS → bibliothèque légère → bibliothèque lourde » se trouvent dans references/decision-tree.md.
§3 VALEURS NUMÉRIQUES (PAS D'INTUITION)
Toutes les durées, courbes et amplitudes proviennent du tableau ci-dessous ; si une valeur n'y figure pas, justifiez-la d'abord avant de l'ajouter.
Durées
| Élément | Valeur |
|---|---|
| hover / press | 120–180 ms |
| toggle / déplier/replier | 200–300 ms |
| Entrée | 240–400 ms |
| Sortie | Durée d'entrée × 0,6–0,7 |
| Transition de page | 300–500 ms |
| Réorganisation de layout (animation layout) | 300–500 ms |
| Intervalle de stagger | 30–50 ms, durée totale du groupe ≤ 500 ms |
| Au-delà de 600 ms | Doit pouvoir être justifié, sinon supprimez |
Easing
| Easing | Courbe |
|---|---|
| Entrée | cubic-bezier(0.16, 1, 0.3, 1) |
| Sortie | cubic-bezier(0.4, 0, 1, 1) |
| Bidirectionnel / changement d'état | cubic-bezier(0.4, 0, 0.2, 1) |
| Déplacement / glisser / geste | spring : stiffness 300–500, damping 30–40 |
| linear | Uniquement barre de progression, décoration en boucle infinie |
Amplitudes
| Amplitude | Valeur |
|---|---|
| Déplacement | Petit 4–8 px / Moyen 12–24 px / Grand 32–64 px / >80 px uniquement pour transition plein écran |
| Opacité | Micro-interaction .9→1 ; entrée .6→1 ; 0→1 uniquement pour masque plein écran et modale |
| Échelle | Uniquement intervalle 0.96–1.04 |
Spring
| Paramètre | Valeur | Justification |
|---|---|---|
| stiffness | 300–500 | En dessous de 300, c'est lent ; au-dessus de 500, ça vibre comme un défaut |
| damping | 30–40 | En dessous de 30, le rebond est excessif ; au-dessus de 40, il n'y a plus de sensation de rebond |
| mass | 0.8–1 | Modification minimale perceptible de l'inertie |
Justification des intervalles, une phrase par point :
- hover / press 120–180 ms : en dessous de 120 ms, on ne perçoit pas le changement d'état ; au-dessus de 180 ms, le retour est lent, l'utilisateur pense avoir cliqué à vide.
- Entrée 240–400 ms : en dessous de 240 ms, on ne perçoit pas la direction du déplacement ; au-dessus de 400 ms, l'utilisateur commence à attendre.
- Sortie × 0,65 : la sortie n'a pas besoin d'être clairement vue ; si elle est lente, elle traîne.
- Stagger 30–50 ms : en dessous de 30 ms, ça ressemble à une apparition simultanée ; au-dessus de 50 ms, le groupe dépasse la ligne de patience de 500 ms.
Ces valeurs sont déjà traduites en variables CSS et constantes TypeScript, voir references/tokens.md ; tout le code doit référencer les tokens, pas de valeurs numériques en dur.
§4 LIGNES ROUGES DE PERFORMANCE ET D'ACCESSIBILITÉ
- Animez uniquement
transform/opacity; pour animer une taille, utilisez FLIP ou la capacitélayoutde la bibliothèque. - Ajoutez
will-change: transformaux couches qui seront animées en continu, retirez-le une fois l'animation terminée. - Virtualisez les longues listes ; mettez en pause les éléments hors écran avec IntersectionObserver.
prefers-reduced-motion: reduceest une branche obligatoire, pas une option bonus. Après la dégradation, le changement d'état doit encore être clair : généralement, on dégrade en un fondu croisé d'opacité ≤ 120 ms (120 ms suffisent pour percevoir le changement d'état, sans constituer une animation nécessitant d'être comprise), ou en un changement direct.- N'utilisez pas de clignotement à plus de 3 fois/seconde (seuil de photosensibilité WCAG 2.3.1).
- Pendant l'animation, ne captez pas le focus, ne perturbez pas l'ordre de tabulation ; l'anneau de focus clavier ne participe pas à l'animation.
- Concevez en vous assurant que « la version statique est également belle », l'animation n'est qu'un plus.
Les clauses WCAG, aria-live, les méthodes de test sont dans references/accessibility.md.
§5 RÈGLES D'IMPLÉMENTATION IMPÉRATIVES
- Les entrées et sorties sont conçues par paires, et la sortie est plus rapide.
- Un seul point focal visuel par écran.
- Stagger de 30–50 ms, pas plus de 500 ms pour l'ensemble du groupe.
- Les couches d'animation décoratives doivent avoir
pointer-events: none. - Enchaînez les animations avec les événements transition/animation,
onAnimationCompleteou timeline, interdiction d'utilisersetTimeout. - Si CSS ou Framer peuvent le faire, n'utilisez pas GSAP.
- Si vous pouvez utiliser
transform, n'animez paswidth/height. - La durée des animations doit être examinée dans le cadre de la revue de design, pas de réglage oral intuitif.
- D'abord enlever, puis ajouter : supprimez d'abord les animations superflues, puis optimisez celles qui ne peuvent pas être supprimées.
§6 MODE DE RÉVISION
Lors de la révision d'animations existantes, chaque point doit être présenté selon les quatre sections fixes suivantes :
Problème / Référence (citer les clauses §1–§4) / Code suggéré / Impact (durée, performance, accessibilité)
Règles :
- Signalez uniquement les vrais problèmes. Ne réécrivez pas une implémentation correcte pour faire du nombre.
- Maximum 8 points, triés par gravité : accessibilité > performance > durée/courbe > style.
- Terminez par un paragraphe « Ces points sont corrects », listez 1–3 éléments, pour éviter que l'utilisateur modifie par erreur une implémentation correcte.
Commande de scan (lecture seule, ne fournissez pas --fix ; toute modification automatique de l'animation détruirait l'intention de conception) :
node ~/.claude/skills/frontend-animation/scripts/audit-animation.mjs <répertoire_du_projet> --json
Le script signale uniquement les problèmes et leur emplacement ; la correction est décidée par l'humain.
§7 LIRE CE QUI SUIT EN FONCTION DU BESOIN
| Symptôme / Besoin | Fichier |
|---|---|
| Vous ne savez pas si utiliser CSS ou une bibliothèque, vous devez choisir entre frameworks, vous devez poser des questions dans l'ordre | references/decision-tree.md |
| Vous devez définir des tokens, intégrer Tailwind, écrire des variables CSS ou des constantes TypeScript | references/tokens.md |
| Vérifier l'installation, l'API, les pièges de version de motion / GSAP / three.js+R3F / Lottie / View Transitions | references/libraries.md |
| Vous avez besoin de modèles prêts à l'emploi (liste d'entrée, transition de route, glisser, suivi de souris, défilement numérique, rotation 3D, fond en boucle, squelette, bouton magnétique, Lottie) | references/patterns.md |
Choisir une courbe d'easing, obtenir une approximation linear() d'un spring, expliquer pourquoi une courbe donnée | references/easing.md |
Dégradation reduced-motion, WCAG, clignotement et focus, méthodes de test | references/accessibility.md |
Vous voulez un composant de référence complet avec une branche reduced-motion | assets/template-component.tsx |
| Vous voulez analyser les problèmes d'animation dans le code existant | scripts/audit-animation.mjs |
§8 AUTO-VÉRIFICATION AVANT DE SOUMETTRE (8 QUESTIONS, RÉPONDEZ À CHACUNE)
- Cette animation est-elle nécessaire ? La version statique reste-t-elle belle sans elle ?
- Animatez-vous uniquement
transform/opacity? - La durée, la courbe et l'amplitude sont-elles dans les limites du §3 ?
- L'entrée et la sortie sont-elles conçues par paires, la sortie est-elle plus rapide ?
- Y a-t-il une branche
reduced-motion? L'état dégradé est-il toujours discernable ? - Avez-vous ajouté une dépendance ? Sans accord, c'est une violation.
- Y a-t-il un clignotement >3 fois/seconde, ou un vol de focus pendant l'animation ?
- Y a-t-il un seul point focal visuel par écran ?
Si une seule question n'a pas de réponse, arrêtez-vous et corrigez avant de soumettre.