JS Libraries & Orchestration
The same scene in GSAP vs Motion vs Anime.js.
At some point hand-rolled requestAnimationFrame loops stop scaling. You need to sequence a dozen elements, stagger them, interrupt mid-flight and have the new
motion inherit velocity. That is what an animation library buys you — a timeline, a
stagger primitive, and a composition model. This chapter compares the three that define the 2025
landscape, running the identical scene in each.
What a library actually gives you
Strip away the marketing and every serious motion library is three ideas stacked on top of the Web Animations API (or its own ticker):
A container that places tweens on a shared playhead. You append with relative offsets
("<", "+=0.2") instead of juggling setTimeout.
A function that turns one target list into N delayed starts — by index, by grid distance, or from a chosen origin. The single most-used choreography tool.
When a new animation hits a moving element, does it restart, blend, or inherit velocity? This is what makes gestures feel alive — and where springs (Ch.4) meet libraries.
The same scene, three ways
Below: a row of six bars rising and fading in with a stagger, implemented in GSAP, Motion
(vanilla motion package), and Anime.js v4 — each in its own component, each reading
the same stagger value from the slider. Hit replay all to fire
all three at once and compare the feel. Note how the API shapes differ while the result
converges.
GSAP & Motion take seconds; Anime.js takes ms — here 80ms.
…and the source behind each panel
import { gsap } from 'gsap';
const tl = gsap.timeline();
tl.fromTo(bars,
{ opacity: 0, y: 28, scaleY: 0.3 },
{ opacity: 1, y: 0, scaleY: 1,
duration: 0.6, ease: 'power3.out',
stagger: 0.08 } // seconds
);import { animate, stagger } from 'motion';
animate(bars,
{ opacity: [0, 1],
transform: ['translateY(28px) scaleY(.3)',
'translateY(0px) scaleY(1)'] },
{ duration: 0.6,
ease: [0.16, 1, 0.3, 1],
delay: stagger(0.08) } // seconds
);import { createTimeline, stagger } from 'animejs';
const tl = createTimeline();
tl.add(bars, {
opacity: [0, 1],
translateY: [28, 0],
scaleY: [0.3, 1],
duration: 600,
ease: 'out(3)',
delay: stagger(80) // milliseconds
});Stagger & ease playground
Choreography lives in two knobs: how far apart the starts are (stagger) and what curve each element travels (ease). Drive an Anime.js timeline live — the bars re-run on every change.
These map directly onto Anime.js's stagger() and ease params.
Edit it live: a grid stagger
The playground below loads Anime.js v4 straight from a CDN into the sandbox. Change the stagger() origin ('center' → 'first' / 'last'),
the grid dimensions, or the ease and watch the ripple change. This is the real library, running
in an iframe — break it freely.