How to Animate Elements with Web Animations API

The Web Animations API (WAAPI) provides a native JavaScript interface that allows developers to create, control, and manipulate CSS-style animations directly in the DOM. By bridging the gap between declarative CSS animations and imperative JavaScript execution, WAAPI offers fine-grained runtime control over dynamic visual effects while maintaining hardware-accelerated rendering performance. This article explains the core mechanics of the API, demonstrating how it executes animations, handles timing configurations, and manages playback states directly through JavaScript.

The Element.animate() Method

The primary entry point for the Web Animations API is the animate() method, available on any DOM element. This method constructs a new Animation object, attaches it to the target element, and automatically begins playback unless configured otherwise.

The method accepts two main arguments: 1. Keyframes: An array of objects representing the CSS style states at various points during the animation. 2. KeyframeAnimationOptions: An object or duration number defining the timing and behavior of the animation.

const box = document.querySelector('.box');

box.animate([
  { transform: 'translateX(0px)', opacity: 1 },
  { transform: 'translateX(200px)', opacity: 0.5 },
  { transform: 'translateX(400px)', opacity: 1 }
], {
  duration: 1000,
  iterations: Infinity,
  easing: 'ease-in-out',
  fill: 'forwards'
});

Keyframes and CSS Property Mapping

Keyframes in WAAPI are defined as JavaScript objects. CSS properties with hyphens are written in camelCase (for example, background-color becomes backgroundColor).

By default, keyframes are distributed evenly across the animation timeline. To set precise timing intervals, an offset property (with a value between 0.0 and 1.0) can be added to individual keyframe objects:

element.animate([
  { opacity: 0, offset: 0 },
  { opacity: 0.8, offset: 0.2 },
  { opacity: 1, offset: 1 }
], {
  duration: 2000
});

Timing and Execution Properties

The options parameter maps directly to standard CSS animation properties:

Performance and the Compositor Thread

WAAPI executes animations using the browser’s internal animation engine rather than JavaScript timer loops like setInterval or continuous requestAnimationFrame style recalculations. When animating composite-friendly properties such as transform and opacity, the browser processes the visual changes directly on the compositor thread (the GPU), ensuring fluid 60fps or 120fps animations independent of main thread JavaScript workload.

Dynamic Playback Control

Unlike standard CSS animations, element.animate() returns an Animation object that provides direct imperative control over playback state at any point during execution.

Key methods include: * animation.play(): Resumes or starts playback. * animation.pause(): Freezes the animation at its current frame. * animation.reverse(): Reverses the playback direction. * animation.finish(): Jumps immediately to the end state. * animation.cancel(): Aborts the animation and removes applied styles.

Developers can also inspect or alter properties in real time, such as changing playbackRate to speed up or slow down visual transitions:

const animation = element.animate(keyframes, options);

// Double the animation speed
animation.playbackRate = 2;

// Listen for completion using Promises
animation.finished.then(() => {
  console.log('Animation completed successfully');
});