timeline

Create complex sequences of animations across multiple elements.

import { timeline } from "motion"

timeline(sequence, options)

Sequence

The timeline sequence is an array:

const sequence = []

This sequence defines animations with the same settings as the animate function:

const sequence = [
  ["nav", { x: 100 }, { duration: 1 }]
];

By default, animations will play one after another:

const sequence = [
  ["nav", { x: 100 }, { duration: 1 }],
  ["nav li", { opacity: 1 }, { duration: 0.3, delay: stagger(0.1) }],
]

at

The timing of subsequent animations can be adjusted with the at option.

Pass a number to define a specific time:

const sequence = [
  ["nav", { opacity: 1 }],
  // This will start 0.5 from the start of the whole timeline:
  ["nav", { x: 100 }, { at: 0.5 }],
]

Pass a string starting with + or - to start relative to the end of the previous animation:

const sequence = [
  ["nav", { opacity: 1 }],
  // This will start 0.5 seconds after the previous animation:
  ["nav", { x: 100 }, { at: "+0.5" }],
  // This will start 0.2 seconds before the end of the previous animation:
  ["nav li", { opacity: 1 }, { at: "-0.2" }],
]

Or pass "<" to start at the same time as the previous segment:

const sequence = [
  ["nav", { opacity: 1 }, { duration: 1 }],
  ["nav", { x: 100 }, { duration: 1 }],
  // This will start at the same time as the x: 100 animation
  ["nav li", { opacity: 1 }, { at: "<" }],
]

Labels

By passing a string in the sequence you can mark that time with a label, to later refer to it with an at:

const sequence = [
  ["nav", { opacity: 1 }, { duration: 2 }],
  "my label",

In the above example, "my label" will be set to the 2 second mark. Later in the sequence, you can refer to the 2 second mark in at by using this label:

["nav li", { opacity: 1 }, { at: "my label" }],

Alternatively, a label can be set absolutely or relatively by passing it as an object with its own at property:

const sequence = [
  ["nav", { opacity: 1 }, { duration: 2 }],
  { name: "my label", at: "-0.5" },

Here, "my label" will be set to the 1.5 second mark.

Forward-filling keyframes

When defining a segment with multiple keyframes, the first keyframe will be forward-filled to the start of the animation.

So in this example, button elements will be set to opacity: 0 at the very start of the animation, and then begin animating after 0.5 seconds:

const sequence = [["button", { opacity: [0, 1] }, { at: 0.5 }]]

Options

duration

Default: Automatically calculated

A duration, in seconds, that the animation will take to complete.

timeline(sequence, { duration: 4 })

By default, this is automatically calculated by the provided sequence. But if provided explicitly, the whole animation will be scaled to fit this duration.

delay

Default: 0

A duration, in seconds, that the animation will be delayed before starting.

timeline(sequence, { delay: 0.5 })

endDelay

Default: 0

A duration, in seconds, that the animation will wait at the end before ending.

timeline(sequence, { endDelay: 0.5 })

direction

Default: "normal"

The direction of animation playback. "normal", "reverse", "alternate", or "alternate-reverse".

timeline(sequence, { direction: "alternate", repeat: 2 })

repeat

Default: 0

The number of times the animation should repeat. Set to Infinity to repeat indefinitely.

timeline(sequence, { repeat: 2 })

defaultOptions

An object of options to use as the default options for each animation in the sequence.

timeline(sequence, {
  defaultOptions: { ease: "ease-in-out" },
})

Returns

timeline returns animation controls

Have you seen Motion DevTools?

It's an incredible new developer tool for Chrome that let you inspect, edit and export Motion One and CSS animations. Animate like the good-ol' days of Flash!