Skip to article

animate

animate() runs easing and spring animations, hardware-accelerated where supported.

The animate() function is a powerful tool for creating and controlling animations.

animate("li", { opacity: 0 })

It comes in two sizes, mini (3.2kb) and hybrid (22kb).

The mini version can animate HTML and SVG styles using native browser APIs for incredible performance.

The hybrid version can additionally animate:

  • Independent transforms (x/y/rotateZ etc)

  • More styles, like mask-image and gradients

  • CSS variables

  • SVG paths

  • Animation sequences

  • Colors/strings/numbers

  • JavaScript objects, Three.js and vgpu

Usage

animate can be imported from the "motion" package:

// Hybrid
import { animate } from "motion"

// Mini
import { animate } from "motion/mini"

HTML & SVG

Both versions of animate are capable of animating HTML and SVG styles either by passing elements directly, or via CSS selectors.

// Element(s)
const box = document.getElementById("box")

animate(box, { opacity: 0 }, { duration: 0.5 })

// CSS selectors
animate("div", { opacity: 0 }, { duration: 0.5 })

Transforms

RotateOpen example

The hybrid version of animate can animate every transform axis independently:

  • Translate: x, y, z

  • Scale: scale, scaleX, scaleY

  • Rotate: rotate, rotateX, rotateY, rotateZ

  • Skew: skewX, skewY

  • Perspective: transformPerspective

The z-axis values need a camera before they show anything on screen. 3D transforms and perspective covers how perspective works and when to set it on the parent instead of the element.

animate("div", { rotate: 360 })

CSS variables

Hybrid animate can animate CSS variables in every browser:

animate(element, { "--rotate": "360deg" })

Mini animate can only animate registered CSS properties in modern browsers.

SVG paths

The hybrid animate function can perform line drawing animations with most SVG elements using three special properties: pathLength, pathSpacing and pathOffset.

animate("circle", { pathLength: [0, 1] })

All three are set as a progress value between 0 and 1, 1 representing the total length of the path.

Path animations are compatible with circle, ellipse, line, path, polygon, polyline and rect elements.

Single values

By passing a to and from value, the hybrid animate will output the latest values to the provided onUpdate callback.

// Numbers
animate(0, 100, {
  onUpdate: latest => console.log(latest)
})

// Colors
animate("#fff", "#000", {
  duration: 2
  onUpdate: latest => console.log(latest)
})
HTML contentOpen example

Motion values

By passing hybrid animate a React motion value, it'll be automatically updated with the latest values.

const x = motionValue(0)

animate(x, 200, { duration: 0.5 })

Objects

Objects can be animated much in the same way as HTML & SVG elements.

const values = {
  x: 100,
  color: "#f00"
}

const animation = animate(values, { x: 200, color: "#00f" })

await animation.finished

console.log(values.x) // 200

3D

Motion can animate Three.js and vgpu in the same timelines as HTML. Both integrations are in Motion+ early access.

Three.js: Three.jsOpen example

Timeline sequences

The hybrid animate() function can also play many animations as one timeline. Pass it an array of animations, called a sequence:

animate([
  ["ul", { opacity: 1 }, { duration: 0.5 }],
  ["li", { x: [-100, 0] }]
])

The timeline can be changed while it plays. See the timeline sequences docs to learn how to schedule segments with at, labels and label offsets, and how to add, move and remove segments, callbacks and pauses.

Stagger

When animating more than one element, it's possible to stagger animations by passing the stagger function to delay.

import { stagger, animate } from "motion"

animate(".item", { x: 300 }, { delay: stagger(0.1) })
StaggerOpen example

Motion along a path

By default, x and y animate in a straight line. Pass arc() to transition.path to bend that line into a curve.

Add to basketOpen example
import { animate, arc } from "motion"

animate(
  ".product",
  { x: 200, y: -120 },
  { duration: 0.6, path: arc() }
)

arc() works with all animations, and you can configure its strength, peak, direction and rotate options. See the arc() docs for the full list.

Options

Animations can be configured with transition options. By default, provided options will affect every animating value.

animate(
  element,
  { x: 100, rotate: 0 },
  { duration: 1 }
)

By providing named transitions, these can be overridden on a per-value basis:

animate(
  element,
  { x: 100, rotate: 0 },
  {
    duration: 1,
    rotate: { duration: 0.5, ease: "easeOut" }
  }
)
Basic animationOpen example

type

type decides the type of animation to use.

Mini animate can either animate with the default keyframes animation, or spring:

import { animate } from "motion/mini"
import { spring } from "motion"

animate(
  element,
  { transform: "translateX(100px)" },
  { type: spring, stiffness: 300 }
)

Hybrid animate has all animation types built-in, and can be set to "tween", "spring" or "inertia".

Tween animations are set with a duration and an easing curve.

Spring animations are either physics-based or duration-based.

Physics-based spring animations are set via stiffness, damping and mass, and these incorporate the velocity of any existing gestures or animations for natural feedback.

SpringOpen example

Duration-based spring animations are set via a duration and bounce. These don't incorporate velocity but are easier to understand.

Inertia animations decelerate a value based on its initial velocity, usually used to implement inertial scrolling.

animate("path", { pathLength: 1 }, { duration: 2, type: "tween" })

duration

Default: 0.3 (or 0.8 if multiple keyframes are defined)

The duration of the animation. Can also be used for "spring" animations when bounce is also set.

animate("ul > li", { opacity: 1 }, { duration: 1 })

ease

The easing function to use with tween animations. Accepts:

  • Easing function name. E.g "linear"

  • An array of four numbers to define a cubic bezier curve. E.g [.17,.67,.83,.67]

  • A JavaScript easing function, that accepts and returns a value 0-1.

These are the available easing function names:

  • "linear"

  • "easeIn", "easeOut", "easeInOut"

  • "circIn", "circOut", "circInOut"

  • "backIn", "backOut", "backInOut"

  • "anticipate"

When animating keyframes, ease can optionally be set as an array of easing functions to set different easings between each value:

animate(
  element,
  { x: [0, 100, 0] },
  { ease: ["easeIn", "easeOut"] }
)

times

When animating multiple keyframes, times can be used to adjust the position of each keyframe throughout the animation.

Each value in times is a value between 0 and 1, representing the start and end of the animation.

animate(
  element,
  { x: [0, 100, 0] },
  { times: [0, 0.3, 1] }
)

There must be the same number of times as there are keyframes. Defaults to an array of evenly-spread durations.

bounce

Default: 0.25

bounce determines the "bounciness" of a spring animation. It accepts values from -1 to 1.

0 is no bounce (critically damped), and 1 is extremely bouncy.

Negative values, down to -1, make the spring overdamped: it starts quicker, then settles more slowly into its target, with no overshoot. The lower the value, the slower the settle. It still arrives at the same time as a bounce of 0, so a negative bounce changes the shape of the motion, not its timing.

animate(
  "section",
  { rotateX: 90 },
  { type: "spring", bounce: 0.25 }
)

visualDuration

If visualDuration is set, this will override duration.

The visual duration is a time, set in seconds, that the animation will take to visually appear to reach its target.

In other words, the bulk of the transition will occur before this time, and the "bouncy bit" will mostly happen after.

This makes it easier to edit a spring, as well as visually coordinate it with other time-based animations.

animate(
  "section",
  { rotateX: 90 },
  { type: "spring", visualDuration: 0.5, bounce: 0.25 }
)

stiffness

Default: 1

Stiffness of the spring. Higher values will create more sudden movement.

animate(
  "section",
  { rotate: 180 },
  { type: "spring", stiffness: 50 }
)

damping

Default: 10

Strength of opposing force. If set to 0, spring will oscillate indefinitely.

animate(
  "section",
  { rotate: 180 },
  { type: "spring", damping: 300 }
)

mass

Default: 1

Mass of the moving object. Higher values will result in more lethargic movement.

animate(
  "feTurbulence",
  { baseFrequency: 0.5 },
  { type: "spring", mass: 0.5 }
)

velocity

Default: Current value velocity

The initial velocity of the spring.

animate(
  ".my-element",
  { rotate: 180 },
  { type: "spring", velocity: 2 }
)

restSpeed

Default: 0.1

End animation if absolute speed (in units per second) drops below this value and delta is smaller than restDelta.

animate(
  ".my-element",
  { rotate: 180 },
  { type: "spring", restSpeed: 2 }
)

restDelta

Default: 0.01

End animation if distance is below this value and speed is below restSpeed. When animation ends, the spring will end.

animate(
  ".my-element",
  { x: 200 },
  { type: "spring", restDelta: 0.5 }
)

delay

Default: 0

Delay the animation by this duration (in seconds).

animate(element, { filter: "blur(10px)" }, { delay: 0.3 })

By setting delay to a negative value, the animation will start that long into the animation. For instance to start 1 second in, delay can be set to -1.

repeat

Default: 0

The number of times to repeat the transition. Set to Infinity for perpetual animation.

animate(
  element,
  { backgroundColor: "#fff" },
  { repeat: Infinity, duration: 2 }
)

repeatType

Default: "loop"

How to repeat the animation. This can be either:

  • loop: Repeats the animation from the start.

  • reverse: Alternates between forward and backwards playback.

  • mirror: Switches animation origin and target on each iteration.

animate(
  element,
  { backgroundColor: "#fff" },
  { repeat: 1, repeatType: "reverse", duration: 2 }
)

repeatDelay

Default: 0

When repeating an animation, repeatDelay will set the duration of the time to wait, in seconds, between each repetition.

animate(
  element,
  { backgroundColor: "#fff" },
  { repeat: 1, repeatDelay: 1 }
)

at

When an animation is a segment in a timeline sequence, at sets when it starts. It can be a time, a label, a label offset or a time relative to the previous segment.

animate([
  ["ul", { opacity: 1 }],
  ["li", { x: [-100, 0] }, { at: "-0.2" }]
])

See scheduling segments for every at value.

onUpdate

A function that's provided the latest animation values.

animate("#fff", "#000", {
  duration: 2
  onUpdate: latest => console.log(latest)
})

Controls

animate() returns animation playback controls. These can be used to pause, play, cancel, change playback speed and more.

In the hybrid version, these controls are a timeline. So you can also add, move and remove segments with the timeline methods.

const animation = animate(element, { opacity: 1 })

animation.time = 0.5
animation.stop()

duration

Returns the duration of the animation.

This is the duration of a single iteration of the animation, without delay or repeat options. It is read-only.

const animation = animate(element, { opacity: 0 })

const duration = animation.duration

time

Gets and sets the current time of the animation.

const animation = animate(x, 100, { duration: 1 })

// Set animation time to 0.5 seconds
animation.time = 0.5

// Get animation time
console.log(animation.time) // 0.5

speed

Gets and sets the current playback speed of the animation.

  • 1 is normal rate.

  • 0.5 is half rate.

  • 2 doubles the playback rate.

  • -1 reverses playback.

const animation = animate(element, { opacity: 0 })

const currentSpeed = animation.speed

// Double current speed
animation.speed = currentSpeed * 2

then()

A Promise-like API that resolves when the animation finishes:

const animation = animate(element, { opacity: 0 })

// Async/await
await animation
console.log("Animation complete")

// Promise
animation.then(() => {
  console.log("Animation complete")
})

pause()

Pauses the animation until resumed with play().

const animation = animate(element, { opacity: 0 })
animation.pause()

play()

Plays an animation.

  • If an animation is paused, it will resume from its current time.

  • If an animation has finished, it will restart.

animation.pause()

// Will resume from 1 second
animation.time = 1
animation.play()

// Will play from start
await animation
animation.play()

complete()

Immediately completes the animation, running it to the end state.

animation.complete()

cancel()

Cancels the animation, reverting it to the initial state.

const animation = animate(element, { opacity: 0 })
animation.cancel()

stop()

Stops the animation.

Any values being animated via the Web Animations API will be committed to the element via style.

Stopped animations cannot be restarted.

const animation = animate(element, { opacity: 0 })
animation.stop()