Performance d'animation : la quête des 60 FPS
Les animations Janky détruisent la sensation de luxe. Comprendre le pipeline de rendu du navigateur (mise en page, peinture, composite) pour obtenir un mouvement fluide et fluide.
Un site Web de luxe semble « lourd » en termes de signification, mais « léger » en termes de performances.
Lorsque je clique sur un bouton, le modal devrait glisser instantanément, comme de la soie sans effort.
S’il bégaie, est en retard ou perd des images, l’illusion se brise.
60 images par seconde (FPS) est la référence.
Pour atteindre 60 FPS, le navigateur dispose de 16,6 millisecondes pour restituer une image.
(1000 ms / 60 images = 16,66 ms).
Si vous prenez 17 ms, vous perdez une image. L’utilisateur voit “Jank”.
Pour résoudre ce problème, vous devez comprendre comment pense le navigateur.
Pourquoi Maison Code en parle
Chez Maison Code Paris, nous agissons comme la conscience architecturale de nos clients. Nous héritons souvent de stacks “modernes” construites sans compréhension fondamentale de l’échelle.
Nous abordons ce sujet car il représente un point de pivot critique dans la maturité de l’ingénierie. Une mise en œuvre correcte différencie un MVP fragile d’une plateforme résiliente de niveau entreprise.
Pourquoi Maison Code obsède plus de 60 FPS
Nous ne vendons pas de produits ; nous vendons des sentiments. Une animation saccadée semble « bon marché ». Cela ressemble à une poignée de porte cassée sur une Ferrari. Nous appliquons un Budget de performances strict pour les animations. Si une animation provoque un Layout Shift, nous la supprimons. Nous pensons que Le mouvement est sémantique. Il explique l’interface. Mais le mouvement sans performance n’est que du bruit.
1. Le pipeline de rendu du navigateur
Lorsque vous mettez à jour un style, le navigateur passe par 3 étapes :
- Mise en page (coûteuse) : calcul de la géométrie. « Quelle est la largeur de cette division ? Où se trouve-t-elle ? »
- Déclenché par le changement :
width,height,left,top,margin.
- Déclenché par le changement :
- Peinture (Moyenne) : Remplissage des pixels.
- Déclenché par le changement :
background-color,border,shadow.
- Déclenché par le changement :
- Composite (pas cher) : disposition des calques.
- Déclenché par le changement :
transform,opacity.
- Déclenché par le changement :
La règle d’or : animez uniquement les propriétés Composite.
- Mauvais :
transition : hauteur 0,3s. (Disposition des déclencheurs sur chaque image = gourmande en CPU). - Bon :
transition : transformation 0,3s. (Triggers Composite uniquement = GPU accéléré).
2. Effet d’échelle vs effet de largeur
Vous voulez qu’un bouton grandisse lorsqu’il est survolé.
- Approche naïve :
Cela écarte tous les éléments voisins. Le navigateur doit recalculer la position de la mise en page entière. Jack..btn: survol { largeur : 120 px ; } - Approche Pro :
Cela promeut le bouton vers un nouveau calque. Le GPU le redimensionne comme une texture. Les éléments voisins ne bougent pas. Lisse. Astuce : utilisez.btn:hover { transformation: échelle(1.1); }will-change: transformpour suggérer au navigateur de promouvoir la couche à l’avance.
3. Technique FLIP (Le tour de magie)
Parfois, vous devez modifier la mise en page (par exemple, réorganiser une liste ou développer une carte). Utilisez le principe FLIP (First, Last, Invert, Play).
- Premier : Mesurez la position de départ
(x : 0). - Dernier : Déplacez l’élément vers la position finale (instantanée). Mesurez-le
(x : 100). - Inverser : utilisez
transformpour le déplacer retour visuellement à la position de départ(transform: translateX(-100px)). - Play : animez la transformation à 0.
L’utilisateur voit un mouvement fluide, mais le navigateur n’a calculé la mise en page qu’une seule fois, puis a animé la transformation.
Les bibliothèques comme Framer Motion gèrent cela automatiquement avec
<motion.div layout>.
4. Bibliothèques d’animation JavaScript
CSS est le plus rapide pour les transitions simples. Pour la physique complexe (ressorts), vous avez besoin de JS.
- Framer Motion : la norme React. Excellent DX, mais taille de bundle importante (30 Ko).
- GSAP : la norme de l’industrie pour les développeurs créatifs. Des délais robustes. Licence coûteuse pour certaines fonctionnalités.
- React Spring : basé sur la physique. Bon pour une sensation « naturelle ».
Conseil de performances : exécutez des animations en dehors du cycle de rendu React. Si votre animation met à jour React State à chaque image, vous tuerez le thread principal. Utilisez des références et une manipulation directe du DOM (ou des bibliothèques qui font cela, comme GSAP).
5. Le goulot d’étranglement mobile (mode faible consommation)
Votre MacBook Pro M3 Max peut tout animer. Le téléphone Android de votre utilisateur, âgé de 3 ans, en « Mode économie de batterie » ne le peut pas. La limitation du processeur est réelle. Test sur des appareils bas de gamme. Si votre effet “Parallax Scroll” rend le téléphone chaud, désactivez-le. Utilisez la requête multimédia « préfère le mouvement réduit » pour respecter les paramètres utilisateur. Un site accessible est un site performant.
6. Débogage des FPS (DevTools)
Ouvrez Chrome DevTools -> onglet Performances. Enregistrez l’animation. Recherchez les Triangles rouges. “Tâche longue”. “Recalculer le style”. Si vous voyez beaucoup d’activité de mise en page (barres violettes), vous animez les mauvaises propriétés. Activez “Paint Flashing” dans l’onglet Rendu. Des flashs verts indiquent ce qui est repeint. Idéalement, rien ne devrait clignoter lors d’une animation de transformation. Bordures de calque : activez cette option pour voir quels éléments sont promus sur le GPU.
7. Le piège useLayoutEffect de React
Dans React, useEffect s’exécute après paint.
Si vous mesurez des éléments DOM dans useEffect, l’utilisateur voit un cadre où l’élément est au mauvais endroit, puis il s’enclenche.
Utilisez useLayoutEffect pour les mesures.
Il bloque la peinture jusqu’à ce que la mesure soit effectuée.
Utilisez-le avec parcimonie, car il met le thread principal en pause.
Mais pour l’initialisation de l’animation (FLIP), il est obligatoire d’éviter les problèmes visuels.
8. Le modèle RAIL (la doctrine de performance de Google)
Google définit 4 moments clés de la performance : R.A.I.L.
- Réponse : traiter les événements en < 50 ms. Si je clique, je dois voir les commentaires instantanément.
- Animation : produisez une image en < 16 ms (60 ips).
- Idle : maximisez le temps d’inactivité. Travaillez lorsque l’utilisateur n’interagit pas.
- Charger : diffusez du contenu et devenez interactif en moins de 5 secondes. Si vous violez RAIL, Google punit votre classement SEO. Il ne s’agit pas seulement de « vitesse ». Il s’agit de “Perception”. Un délai de 100 ms équivaut à 1 seconde pour un utilisateur.
9. Hors du fil conducteur : les travailleurs du Web
JavaScript est monothread. Si vous analysez un énorme fichier JSON, l’interface utilisateur se bloque. Solution : Web Workers. Déplacez la logique lourde (analyse des données, compression d’images, cryptage) vers un travailleur.
const travailleur = nouveau travailleur('worker.js');
travailleur.postMessage(hugeData);
Le fil principal reste gratuit pour l’interface utilisateur (défilement, clic). Les bibliothèques comme Comlink facilitent cela. En 2026, « l’architecture hors-thread principal » sera la valeur par défaut.
10. Étude de cas : Le carrousel 60FPS
Nous avons construit un carrousel de produits pour un client de mode de luxe.
Contrainte : 50 images haute résolution. Parchemin infini. Transitions 3D.
Échec de la V1 : état de réaction activeIndex. Rendu de la liste entière à chaque balayage. 15 IPS.
V2 fixe :
- Virtualisation : rendu uniquement des 3 diapositives visibles.
- Correction : utilisé
transform: translateX3d()pour l’accélération matérielle. - Will-Change : a laissé entendre le navigateur.
- Décodage d’images : utilisé
decoding="async"sur les images. Résultat : 60 FPS solides sur un iPhone 8. La différence n’était pas le cadre ; c’était la physique du navigateur.
11. WebGL et Canvas (casser le DOM)
Pour les animations extrêmes (milliers de particules, modèles 3D), le DOM est trop lent. Passez à WebGL (via Three.js ou React Three Fiber). WebGL dessine directement dans le tampon GPU. Il contourne entièrement le pipeline Layout/Paint. C’est ainsi que nous construisons des expériences de luxe de style “Awwwards”. Mais attention : l’accessibilité devient beaucoup plus difficile en WebGL. Canvas ne prend pas en charge les lecteurs d’écran par défaut.
12. Le compteur FPS (Observabilité)
Vous ne pouvez pas réparer ce que vous ne pouvez pas mesurer.
Chrome dispose d’un compteur FPS, mais pas les utilisateurs.
Nous injectons un tout petit FPS Listener en production (pour 1% des utilisateurs).
Il utilise la boucle requestAnimationFrame pour mesurer le temps delta.
Si les images tombent en dessous de 30 pendant 5 secondes, nous enregistrons un événement dans Sentry.
« Performances : faible FPS détecté sur /product/123 ».
Cela nous indique exactement quelle page est lourde dans le monde réel (pas seulement sur notre MacBook Pro).
13. Les formats d’image (Avif vs WebP)
L’animation n’est pas seulement du CSS ; ça charge. Si votre image de héros met 3 secondes à se charger, l’animation d’entrée bégaie. WebP est la norme. AVIF est l’avenir (20 % plus petit que WebP). Mais les navigateurs doivent les décoder sur le thread principal (la plupart du temps). Stratégie :
- Utilisez la balise
<picture>comme solution de secours. - Utilisez l’attribut
decoding="async"sur<img>. - BlurHash : affiche un petit flou de 20 px pendant le chargement de l’image lourde. Cela réduit la « latence perçue ».
14. Conclusion
La performance n’est pas une réflexion après coup. C’est une contrainte de conception. Si vous ne pouvez pas l’animer à 60 FPS, ne l’animez pas du tout. Une interface statique vaut mieux qu’une interface lente. Respectez la batterie de l’utilisateur. Respectez le temps de l’utilisateur. Faites-le voler.
Les chutes de cadre tuent l’ambiance ?
Nous auditons les performances du frontend et optimisons les animations pour 60 FPS sur les appareils bas de gamme.