What Is the Web Animations API? JS-Native Animation
The Web Animations API lets JavaScript create and control animations natively, combining CSS-animation performance with imperative, scriptable control.
The Web Animations API (WAAPI) is a browser-native JavaScript interface for creating and controlling animations, exposed through a single method — element.animate() — that returns an Animation object you can play, pause, reverse, and inspect from script. It sits deliberately between two older options: it runs with the same browser-optimized performance as CSS animations, but with the imperative, scriptable control that used to mean writing your own requestAnimationFrame loop.
The basic shape
animate() takes a set of keyframes and a timing configuration, and hands back a live Animation object:
const box = document.querySelector('.box');
const animation = box.animate(
[
{ transform: 'translateX(0)', opacity: 1 },
{ transform: 'translateX(200px)', opacity: 0.5 },
],
{
duration: 400,
easing: 'ease-out',
fill: 'forwards',
}
);
The keyframes array is functionally the same idea as a CSS @keyframes block, just expressed as JavaScript objects. The options object covers what a CSS animation shorthand would: duration, easing, delay, iteration count, direction, and fill (whether the animation’s end state persists once it finishes).
Controlling it after the fact
This is the part CSS animations can’t do without JavaScript hacks like toggling class names. The returned Animation object exposes methods and properties for live control:
animation.pause();
animation.play();
animation.reverse();
animation.playbackRate = 2; // double speed
animation.finished.then(() => { // a promise that resolves on completion
console.log('animation done');
});
Because finished is a promise, sequencing animations — running one after another, or waiting for an animation to complete before updating application state — becomes a matter of await, not manually tracking animationend event listeners and matching them up with the right element.
Why not just use CSS animations
CSS animations and transitions are declarative and let the browser’s compositor handle the heavy lifting, which is why they stay smooth even under load — the same reason they’re the default recommendation in CSS transitions vs animations. What they don’t give you is fine-grained runtime control: you can’t easily pause a CSS animation partway through and query exactly how far along it is, reverse it cleanly, or change its playback rate on the fly. Getting that behavior with pure CSS usually means toggling classes and reading back computed styles — workable, but fragile.
WAAPI keeps the same compositor-driven performance characteristics as CSS animations (the browser can still run many of these animations off the main thread) while giving script the level of control that used to require requestAnimationFrame — the older approach of manually computing each frame’s state in a callback loop tied to the display’s refresh rate. requestAnimationFrame is still the right tool when an animation’s path genuinely depends on continuous input, like following a pointer or physics-based motion that can’t be expressed as a fixed set of keyframes. For everything with a defined start and end state that just needs to be interactively controllable, WAAPI is usually the simpler choice.
Comparing the three approaches
| CSS animations | Web Animations API | requestAnimationFrame | |
|---|---|---|---|
| Defined in | Stylesheet | JavaScript | JavaScript |
| Runtime control (pause/reverse/rate) | Limited, via class toggling | Native — play/pause/reverse/rate | Fully manual |
| Performance | Compositor-optimized | Compositor-optimized | Depends on your per-frame code |
| Best for | Static, declarative UI transitions | Interactive or JS-driven animations with a defined end state | Continuous, input-driven motion |
Where it shows up in practice
Because WAAPI produces a standard Animation object, it composes cleanly with other browser APIs rather than requiring its own separate animation library for basic cases. The View Transitions API, for instance, is built on the same underlying animation model — a view transition is, under the hood, a set of pseudo-elements animated the same way element.animate() would animate them, which is part of why customizing a view transition’s timing uses familiar keyframe and easing concepts. WAAPI is also a natural fit for animating elements you’re already manipulating through the DOM in response to application state changes, since the same JavaScript that updates state can kick off and await the corresponding animation.
The takeaway
The Web Animations API gives JavaScript native, promise-based control over animations — play, pause, reverse, change speed, and await completion — while keeping the compositor-driven performance CSS animations are known for. Reach for it over CSS when an animation needs to be paused, reversed, or otherwise controlled at runtime in response to user interaction or application state; reach for requestAnimationFrame instead when the animation’s path can’t be expressed as a fixed set of keyframes at all. For most other UI motion, plain CSS transitions and animations remain the simplest option.
Tagged
Keep reading
Takina · · 4 min read Object.groupBy() in JavaScript, Explained
Object.groupBy() buckets array items by a key you compute, replacing the reduce() boilerplate developers have written for years. How it works.
Takina · · 4 min read Web Locks API: Coordinating Work Across Browser Tabs
The Web Locks API lets JavaScript acquire named locks shared across tabs, so only one tab does work like a token refresh or a write at a time.
Takina · · 4 min read Svelte 5 Runes Explained
Svelte 5 runes like $state and $derived replace the old reactive-assignment magic with explicit function calls that work anywhere in a file.