Edit Page

#Animation

A set of properties and helpers for high-performance, declarative animations.

Animations in Motion are primarily controlled via the motion component's animate property.

It can accept a target object, variant label(s), or imperative animation controls. We'll explore each on this page.

import { motion } from "framer-motion"

export const MyComponent = () => (
  <motion.div
    animate={{ rotate: 360 }}
    transition={{ duration: 2 }}
  />
)

#Target object

The simplest way to make a component animate is to pass a target object to a component's animate prop.

<motion.div animate={{ x: 100 }} />

When any value in animate changes, the component will automatically animate to the updated target.

#Transitions

By default, Motion will create an appropriate animation for a snappy transition based on the types of value being animated. For instance, physical properties like x or scale will be animated via a spring simulation. Whereas values like opacity or color will be animated with a tween.

However, you can set different types of animation by passing a Transition to the transition prop.

<motion.div
  animate={{ x: 100 }}
  transition={{ ease: "easeOut", duration: 2 }}
/>

#Mount animations

When a component mounts, it'll automatically animate to the values in animate if they're different from those defined in style or initial. You can set the initial prop to false to use the value in animate as the component's mounted state to disable mount animations.

<motion.div animate={{ x: 100 }} initial={false} />

This will also work with server-side rendering.

#Keyframes

Values in animate can also be set as a series of keyframes. This will animate through each value in sequence.

<motion.feGaussianBlur
  animate={{ stdDeviation: [0, 5, 0] }}
/>

By default, a keyframes animation will start with the first item in the array. To use the current value instead, null can be passed as a placeholder. This way, if a keyframes animation starts while the value is currently animating, the transition will be more natural.

<motion.circle cx={500} animate={{ cx: [null, 100] }} />

Each of these keyframes will be spaced equidistantly throughout the animation, but you can override this by setting a times prop on the transition prop.

This is an array of the same length as the animation target with numbers between 0 and 1 that define when in the animation each keyframe should be hit.

<motion.circle
  cx={500}
  animate={{ cx: [null, 100, 200] }}
  transition={{ duration: 3, times: [0, 0.2, 1] }}
/>

#Variants

Target objects are useful for simple, single-component animations. But sometimes we want to create animations that propagate throughout the DOM, and orchestrate those animations in a declarative way. We can do so with variants.

Variants are sets of pre-defined target objects.

const variants = {
  visible: { opacity: 1 },
  hidden: { opacity: 0 },
}

They're passed into motion components via the variants prop.

<motion.div variants={variants} />

These variants can be referred to by label, whereever you can set an animation target.

<motion.div
  initial="hidden"
  animate="visible"
  variants={variants}
/>

#Propagation

If a motion component has children, changes in variant will flow down through the component hierarchy. These changes in variant will flow down until a child component defines its own animate property.

const list = {
  visible: { opacity: 1 },
  hidden: { opacity: 0 },
}

const items = {
  visible: { opacity: 1, x: 0 },
  hidden: { opacity: 0, x: -100 },
}

return (
  <motion.ul
    initial="hidden"
    animate="visible"
    variants={list}
  >
    <motion.li variants={item} />
    <motion.li variants={item} />
    <motion.li variants={item} />
  </motion.ul>
)

#Orchestration

By default, all these animations will start simultaneously. But by using variants, we gain access to extra transition props like when, delayChildren, and staggerChildren that can let parents orchestrate the execution of child animations.

const list = {
  visible: {
    opacity: 1,
    transition: {
      when: "beforeChildren",
      staggerChildren: 0.3,
    },
  },
  hidden: {
    opacity: 0,
    transition: {
      when: "afterChildren",
    },
  },
}

#Dynamic variants

Each variant can be defined as a function that resolves when a variant is accessed. These variant functions are provided a single argument, which can be set in a component's custom prop.

const variants = {
  visible: i => ({
    opacity: 1,
    transition: {
      delay: i * 0.3,
    },
  }),
  hidden: { opacity: 0 },
}

return items.map((item, i) => (
  <motion.li
    custom={i}
    animate="visible"
    variants={variants}
  />
))

#Animation controls

Declarative animations are ideal for most UI interactions. But sometimes we need to orchestrate more complex sequences.

The useAnimation hook can be used to create a set of imperative AnimationControls with a start and stop method. These controls can be passed to one or more motion components via the animate prop.

const MyComponent = () => {
  const controls = useAnimation()

  return <motion.div animate={controls} />
}

#Starting an animation

Animations can be started with the controls.start method.

controls.start({
  x: "100%",
  backgroundColor: "#f00",
  transition: { duration: 3 },
})

start accepts either a TargetAndTransition or, if the component(s) it's provided to has a variants property set, a variant label.

controls.start("hidden")

#Sequencing

start returns a Promise, so it can be used to sequence animations using await or then.

Different controls can be sequenced together, and these sequences can be composed into functions that themselves can then be sequenced.

const sequence = async () => {
  await menuControls.start({ x: 0 })
  return await itemControls.start({ opacity: 1 })
}

#Dynamic start

start can also accept a function that can dynamically start each component the controls are bound to with a different animation definition.

Custom data can be sent to this function via the component's custom prop.

const controls = useAnimation()

useEffect(() => {
  controls.start(i => ({
    opacity: 0,
    x: 100,
    transition: { delay: i * 0.3 },
  }))
}, [])

return (
  <ul>
    <motion.li custom={0} animate={controls} />
    <motion.li custom={1} animate={controls} />
    <motion.li custom={2} animate={controls} />
  </ul>
)