La plupart des développeurs restent ancrés à CSS transitions et jQuery animate(), alors que le Web Animations API (WAAPI) offre un contrôle programmatique sur les animations sans déléguer au moteur CSS. Contrairement aux transitions CSS, la WAAPI permet de synchroniser plusieurs animations, de les mettre en pause, d'ajuster leur timeline en temps réel, et surtout de lire l'état actuel sans déclencher de reflow. C'est particulièrement pertinent dans Angular où vous gérez des états complexes : une modal qui slide tout en fading, une liste qui se réordonne avec parallélisation d'animations, ou une progression qui se synchronise avec des appels API.
Comprendre la composition et éviter les repaints inutiles
Le cœur du problème de performance n'est pas l'API elle-même, mais ce qu'elle anime. Animer la propriété left ou width force le navigateur à recalculer le layout à chaque frame — c'est l'ennemi juré du jank. À l'inverse, animer transform et opacity ne touche qu'à la couche composite, opération quasi-gratuite au niveau du GPU. Quand vous utilisez WAAPI sur une propriété "cheap", vous obtenez 60 fps stable ; sur une propriété "expensive", vous dégringlez à 30 fps ou pire. La subtilité : CSS ne vous dit pas automatiquement quelle propriété anime où. Vous devez inspecter manuellement avec DevTools (Performance tab, Layout Shift) pour vérifier. Un exemple concret : une sidebar qui coulisse. Si vous animez marginLeft: '0' → 'marginLeft: -300px' , vous forcez un reflow global. Si vous animez transform: translateX(0) → translateX(-300px) , c'est un seul recomposite.
Avec WAAPI, cette distinction est même plus critique car vous pouvez chainer des centaines d'animations. Chaque animation sur une propriété coûteuse devient un hotspot. Utilisez will-change: transform ou contain: layout pour signaler au navigateur que vous allez animer, ce qui le pousse à créer une couche composite d'avance. Cependant, will-change a un coût mémoire : l'activer sur 50 éléments ralentit tout. Ciblage fin, donc.
Synchronisation et coordination : le vrai bénéfice de WAAPI
Supposons une animation complexe : un formulaire qui glisse, ses champs fade-in séquentiellement, et une barre de progression qui advance parallèlement. Avec CSS seul, vous empilerez des animations multiples et vous perdrez le contrôle de la synchronisation dès que l'état change (l'utilisateur cancel, ou l'API répond plus tôt). Avec WAAPI, vous créez une timeline parent et attachez les sous-animations avec des offset précis. Voici un exemple simplifié :
const timeline = document.timeline; // AnimationTimeline
const slidingElement = document.querySelector('.form-slide');
const progressBar = document.querySelector('.progress');
const slideAnim = slidingElement.animate(
[{ transform: 'translateX(-100%)' }, { transform: 'translateX(0)' }],
{ duration: 800, fill: 'forwards' }
);
const progressAnim = progressBar.animate(
[{ width: '0%' }, { width: '100%' }],
{ duration: 800, fill: 'forwards' }
);
// Attendre que les deux terminent
Promise.all([slideAnim.finished, progressAnim.finished]).then(() => {
console.log('Animations complètes');
}); Le vrai pouvoir vient du .ready et du .finished promises, qui vous permettent d'orchestrer des cascades d'animations sans setTimeout fragile. Vous pouvez aussi mettre en pause, ajuster la playbackRate (ralentir/accélérer), ou réinitialiser via .cancel() . C'est impossible avec CSS pur. Dans une app Angular, vous enveloppez ça dans une directive ou un service pour que les composants ne connaissent pas l'implémentation.
Pièges courants et optimisations critiques
Le piège majeur : oublier que chaque .animate() crée une animation JavaScript en attente du navigateur. Si vous animez 100 éléments simultanément sans coordination, vous saturez le thread de composition. Résultat : jank immédiat. Groupez les animations avec des timeouts ou des AnimationFrames pour les étaler. Deuxième piège : animer sur des propriétés non-animables. Par exemple, animer display: none → display: block ne fonctionne pas ; vous devez utiliser opacity ou visibility + pointer-events . Troisième piège : ignorer le fill property. Par défaut, fill: 'none' signifie que l'élément revient à son état d'avant l'animation une fois terminée — contre-intuitif. Utilisez fill: 'forwards' pour conserver l'état final.
Une optimisation souvent ignorée : les animations WAAPI ne bénéficient pas automatiquement des GPU-accelerations si la propriété n'est pas "compositable". Forcez la création d'une couche avec transform: translateZ(0) ou will-change: transform avant de lancer l'animation. Cela coûte quelques millisecondes au lancement mais gagne énormément en fluidité. Testez toujours avec DevTools et l'option "Show compositing borders" — vous verrez immédiatement si votre animation a sa propre couche GPU ou non.
Intégration dans Angular
Dans Angular, envelopper WAAPI dans un service réactif est la bonne pratique. Utilisez un signal pour l'état de l'animation (running, finished, cancelled) et émettez des événements pour que les composants réagissent. Si vous utilisez NgRx ou SignalStore, la timeline de l'animation devient une source d'événements comme une autre. L'avantage : vous pouvez debouncer, fusionner ou transformer les événements d'animation avec RxJS ou signals, ce que CSS seul ne permet jamais. Une directive réutilisable qui expose @Input pour configurer la durée, le type d'animation, et les propriétés cibles rend le code maintenable.
Pour les cas critiques (carrousels, listes virtualisées), considérez IntersectionObserver couplé à WAAPI : n'animez que ce qui est visible. Cela réduit drastiquement la charge CPU sur mobile. Testez sur un vrai téléphone (pas le simulateur) ; un iPhone 11 affiche rapidement ses limites quand vous animez 20 éléments en parallèle.
Conclusion
Le Web Animations API n'est pas une balle magique, mais un outil de précision. Maîtriser la composition (transform + opacity), la synchronisation (promises + playbackRate) et les pièges (fill, propriétés coûteuses, saturation du thread) vous permet de créer des animations fluides et responsives que CSS seul ne peut pas coordonner. Commencez par profiler avec DevTools, identifiez les hotspots, puis appliquez WAAPI là où vous en avez réellement besoin : synchronisation complexe, animations conditionnelles, ou contrôle en temps réel basé sur l'input utilisateur. Pour tout le reste, restez à CSS — c'est plus simple et tout aussi performant.