Edit Page

#Animation

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

Animations in Framer are primarily controlled via the Frame component. The key properties are animate and transition, which take a variety of options to customize animations. All the animation properties and helpers are included when you import Frame, with the exception of useCycle. You can find all the Frame animation properties and methods here.


Framer Library v0.10 and earlier used an older Animation API. Learn more ›
import * as React from "react"
import { Frame } from "framer"

export function MyComponent() {
  return (
    <Frame
      animate={{ rotate: 360 }}
      transition={{ duration: 2 }}
    />
  )
}

#Overview

#Frame

Most animations are controlled via the Frame component, where you can set animations, options and listen for updates. The specific Frame properties relating to animations are linked to below.

import * as React from "react"
import { Frame } from "framer"

export function MyComponent() {
  function onUpdate({ rotate }) {
    console.log(rotate)
  }

  return (
    <Frame
      initial={{ rotate: 0 }}
      animate={{ rotate: 360 }}
      transition={{ duration: 2 }}
      onUpdate={onUpdate}
    />
  )
}

#Animate

Animations are controlled with the animate property. When the values in animate change, the Frame will automatically animate to them.

<Frame animate={{ opacity: 0 }} />

#Transitions

The transition for the values in animate can be set via the transition property.

Transition options include:

  • Tween with a linear or easing curve and given duration.
  • Spring based on mass, damping and stiffness.
  • Inertia spring and friction combined scroll physics.
<Frame
  animate={{ opacity: 0 }}
  transition={{ duration: 1 }}
/>

#Initial State

An initial visual state can be set with the initial property. This gives you a visual default for your Frame to begin with.

<Frame initial={{ scale: 0 }} animate={{ scale: 1 }} />

#Variants

Variants are visual states that can be defined externally from a Frame and passed in via the variants property. This allows variant labels to be used in place of values on the animate, initial, press, and hover properties.

  • The initial state is set to "hidden".
  • The hidden variant gets a custom transition.
  • The Frame animates from its default to visible.
  • The entire variants object is passed to the Frame.
export function MyComponent() {
  const variants = {
    hidden: {
      opacity: 0,
      transition: { duration: 0.5 },
    },
    visible: { opacity: 1 },
  }

  return (
    <Frame
      initial="hidden"
      animate="visible"
      variants={variants}
    />
  )
}

#Animating Children

A child Frame can be animated with variants of the same name triggered by the parent. These variant changes will propagate throughout children, even those that aren't direct children.

For this to work however, you cannot use the animate property on a child Frame. If you do, variant changes from the parent will be ignored and the child Frame will use the animate property instead.

export function MyComponent() {
  // Parent variants
  const list = {
    hidden: { opacity: 0, x: -100 },
    visible: { opacity: 1, x: 0 },
  }

  // Child variants
  const item = {
    hidden: { opacity: 0, scale: 0.5 },
    visible: { opacity: 1, scale: 1 },
  }

  return (
    <Frame
      variants={list}
      initial="hidden"
      animate="visible"
    >
      <Frame variants={item} />
      <Frame variants={item} />
      <Frame variants={item} />
    </Frame>
  )
}

#Parent & Child Orchestration

When animating children, parent variants can schedule child animations using the orchestration properties of transition.

See all orchestration options ›

const list = {
  hidden: {
    opacity: 0,
    x: -100,
    transition: { when: "afterChildren" },
  },
  visible: {
    opacity: 1,
    x: 0,
    transition: { when: "beforeChildren" },
  },
}

#Dynamic Variants

Variants can be set as functions to dynamically generate variant settings. When a component animates to a dynamic variant, it’ll pass its own props to that function, allowing each component to get a modified animation.

Here, we create a staggered animation by passing along the custom property to each Frame, and in the variant definition. All Frames share the same variants object, and animate to the same hidden variant—they only differ in their indices.

export function MyComponent() {
  const variants = {
    hidden: custom => ({
      opacity: 0,
      transition: { delay: custom * 0.5 },
    }),
  }
  return (
    <Stack>
      <Frame
        custom={0}
        variants={variants}
        animate={"hidden"}
      />
      <Frame
        custom={1}
        variants={variants}
        animate={"hidden"}
      />
      <Frame
        custom={2}
        variants={variants}
        animate={"hidden"}
      />
    </Stack>
  )
}

#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.

import { Frame, useAnimation } from "framer"

function MyComponent() {
  const controls = useAnimation()

  return <Frame 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.

async function sequence() {
  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 (
  <>
    <Frame custom={0} animate={controls} />
    <Frame custom={1} animate={controls} />
    <Frame custom={2} animate={controls} />
  </>
)

#Supported Value Types

  • Numbers
  • Strings
  • All Unit Types (px, %, calc(), etc.)
  • Colors (hex, rgba, hsla)
  • Complex Values (Strings with numbers and colors)

When animating complex values, for instance boxShadow, all non-numerical portions of the value must be in the exact same format in every state. For instance, "5px 10px #333" can be animated to "0px 0px #333" but not "0 0 #333".

export function MyComponent() {
  const animate = {
    x: 0,
    y: "100%",
    display: "block",
    color: "rgba(0, 0, 0, 0.5)",
    boxShadow: "5px 10px #333",
  }

  return <Frame animate={animate} />
}

#Transforms

Transform values can be animated as separate values.

  • x, y, z
  • rotate, rotateX, rotateY, rotateZ
  • scale, scaleX, scaleY, scaleZ
  • skewX, skewY
  • originX, originY
  • perspective
<Frame animate={{ rotate: 90, scaleX: 1.2 }} />

#Value Conversion

The properties x, y, width, height, top, left, bottom and right can be animated between different value types.

const variants = {
  closed: { x: 0 },
  open: { x: "calc(50vw - 50%)" },
}

#Tween

An animation that animates between two or more values over a specific duration of time. This is the default animation for non-physical values like color and opacity.

#type: "tween"

Set type to "tween" to use a duration-based tween animation. If any non-orchestration transition values are set without a type property, this is used as the default animation.

<Frame
  animate={{ opacity: 0 }}
  transition={{ duration: 2, type: "tween" }}
/>

#duration: number

The duration of the tween animation. Set to 0.3 by default, 0r 0.8 if animating a series of keyframes.

<Frame
  animate={{ opacity: 0 }}
  transition={{ duration: 2 }}
/>

#ease: Easing | Easing[]

The easing function to use. Set as one of the below.

  • The name of an existing easing function.
  • An array of four numbers to define a cubic bezier curve. An easing function, that accepts and returns a value 0-1.

If the animating value is set as an array of multiple values for a keyframes animation, ease can be set as an array of easing functions to set different easings between each of those values.

const transition = {
  ease: [0.17, 0.67, 0.83, 0.67]
}

<Frame
  animate={{ opacity: 0 }}
  transition={transition}
/>

These strings are the built-in named easing functions in Framer.

  • "linear"
  • "easeIn", "easeOut", "easeInOut"
  • "circIn", "circOut", "circInOut"
  • "backIn", "backOut", "backInOut"
  • "anticipate"

#from: number | string

The value to animate from. By default, this is the current state of the animating value.

const transition = {
  from: 90,
  duration: 2
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#loop: number

The number of times to loop the animation. Set to Infinity for perpetual looping.

const transition = {
  loop: Infinity,
  ease: "linear",
  duration: 2
}

<Frame
  animate={{ rotate: 360 }}
  transition={transition}
/>

#flip: number

The number of times to flip the animation by swapping the to and from values. Set to Infinity for perpetual flipping.

const transition = {
  flip: Infinity,
  duration: 2
}

<Frame
  animate={{ opacity: 0 }}
  transition={transition}
/>

#yoyo: number

The number of times to reverse the animation. Set to Infinity for perpetual reversing.

const transition = {
  yoyo: Infinity,
  duration: 2
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#repeatDelay: number

When repeating an animation using loop, flip, or yoyo, repeatDelay can set the duration of the time to wait, in seconds, between each repetition.

const transition = {
  yoyo: Infinity,
  repeatDelay: 1
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#times: number[]

When animating keyframes, times can be used to determine where in the animation each keyframe is reached. Each value in times is a value between 0 and 1, representing duration.

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

const transition = {
  times: [0, 0.1, 0.9, 1]
}

<Frame
  animate={{ scale: [0, 1, 0.5, 1] }}
  transition={transition}
/>

#Spring

An animation that simulates spring physics for realistic motion. This is the default animation for physical values like x, y, scale and rotate.

#type: "spring"

Set type to "spring" to animate using spring physics for natural movement. Type is set to "spring" by default.

const transition = {
  type: "spring"
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#damping: number

Strength of opposing force. If set to 0, spring will oscillate indefinitely. Set to 10 by default.

const transition = {
  type: "spring",
  damping: 300
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#mass: number

Mass of the moving object. Higher values will result in more lethargic movement. Set to 1 by default.

const transition = {
  type: "spring",
  mass: 0.5
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#stiffness: number

Stiffness of the spring. Higher values will create more sudden movement. Set to 100 by default.

const transition = {
  type: "spring",
  stiffness: 50
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#velocity: number

The initial velocity of the spring. By default this is the current velocity of the component.

const transition = {
  type: "spring",
  velocity: 2
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#restSpeed: number

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

const transition = {
  type: "spring",
  restSpeed: 0.5
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#restDelta: number

End animation if distance is below this value and speed is below restSpeed. When animation ends, spring gets “snapped” to. Set to 0.01 by default.

const transition = {
  type: "spring",
  restDelta: 0.5
}

<Frame
  animate={{ rotate: 180 }}
  transition={transition}
/>

#Inertia

The animation that occurs after you release a draggable Frame. It decelerates a value based on its initial velocity. Optionally, min and max boundaries can be defined, and inertia will snap to these with a spring animation. This animation will automatically precalculate a target value, which can be modified with the modifyTarget property. This allows you to add snap-to-grid or similar functionality.

#bounceDamping: number

If min or max is set, this affects the damping of the bounce spring. If set to 0, spring will oscillate indefinitely. Set to 10 by default.

const transition = {
  min: 0,
  max: 100,
  bounceDamping: 8
}

<Frame
  drag
  dragTransition={transition}
/>

#bounceStiffness: number

If min or max is set, this affects the stiffness of the bounce spring. Higher values will create more sudden movement. Set to 500 by default.

const transition = {
  min: 0,
  max: 100,
  bounceStiffness: 100
}

<Frame
  drag
  dragTransition={transition}
/>

#max: number

Maximum constraint. If set, the value will "bump" against this value (or immediately snap to it, if the initial animation value exceeds this value).

<Frame
  drag
  dragTransition={{ min: 0, max: 100 }}
/>

#min: number

Minimum constraint. If set, the value will "bump" against this value (or immediately spring to it if the animation starts as less than this value).

<Frame
  drag
  dragTransition={{ min: 0, max: 100 }}
/>

#power: number

A higher power value equals a further target. Set to 0.8 by default.

const transition = {
  min: 0,
  max: 100,
  power: 0.2
}

<Frame
  drag
  dragTransition={transition}
/>

#restDelta: number

End the animation if the distance to the animation target is below this value, and the absolute speed is below restSpeed. When the animation ends, the value gets snapped to the animation target. Set to 0.01 by default. Generally the default values provide smooth animation endings, only in rare cases should you need to customize these.

const transition = {
  min: 0,
  max: 100,
  restDelta: 10
}

<Frame
  drag
  dragTransition={transition}
/>

#timeConstant: number

Adjusting the time constant will change the duration of the deceleration, thereby affecting its feel. Set to 700 by default.

const transition = {
  min: 0,
  max: 100,
  timeConstant: 200
}

<Frame
  drag
  dragTransition={transition}
/>

#modifyTarget(v): number

A function that receives the automatically-calculated target and returns a new one. Useful for snapping the target to a grid.

const transition = {
  power: 0,
  // Snap calculated target to nearest 50 pixels
  modifyTarget: target => Math.round(target / 50) * 50
}

<Frame
  drag
  dragTransition={transition}
/>
v: number
returns: number

#Orchestration

Options for orchestrating the timing of animations to build staggered animations or sequences.

#delay: number

Delay the animation by this duration (in seconds). Defaults to 0.

const transition = {
  delay: 0.2
}

#delayChildren: number

When using variants, children animations will start after this duration (in seconds). You can add the transition property to both the Frame and the variant directly. Adding it to the variant generally offers more flexibility, as it allows you to customize the delay per visual state.

const container = {
  hidden: { opacity: 0 },
  show: {
    opacity: 1,
    transition: {
      delayChildren: 0.5
    }
  }
}

const item = {
  hidden: { opacity: 0 },
  show: { opacity: 1 }
}

return (
  <Frame
    variants={container}
    initial="hidden"
    animate="show"
  >
    <Frame variants={item} size={50} />
    <Frame variants={item} size={50} />
  </Frame>
)

#staggerChildren: number

When using variants, animations of child components can be staggered by this duration (in seconds).

For instance, if staggerChildren is 0.01, the first child will be delayed by 0 seconds, the second by 0.01, the third by 0.02 and so on.

The calculated stagger delay will be added to delayChildren.

const container = {
  hidden: { opacity: 0 },
  show: {
    opacity: 1,
    transition: {
      staggerChildren: 0.5
    }
  }
}

const item = {
  hidden: { opacity: 0 },
  show: { opacity: 1 }
}

return (
  <Frame
    variants={container}
    initial="hidden"
    animate="show"
  >
    <Frame variants={item} size={50} />
    <Frame variants={item} size={50} />
  </Frame>
)

#staggerDirection: 1 | -1

The direction in which to stagger children.

A value of 1 staggers from the first to the last while -1 staggers from the last to the first.

const container = {
  hidden: { opacity: 0 },
  show: {
    opacity: 1,
    transition: {
      delayChildren: 0.5,
      staggerDirection: -1
    }
  }
}

const item = {
  hidden: { opacity: 0 },
  show: { opacity: 1 }
}

return (
  <Frame
    variants={container}
    initial="hidden"
    animate="show"
  >
    <Frame variants={item} size={50} />
    <Frame variants={item} size={50} />
  </Frame>
)

#when: false | "beforeChildren" | "afterChildren" | string

Describes the relationship between the transition and its children. Set to false by default.

When using variants, the transition can be scheduled in relation to its children with either "beforeChildren" to finish this transition before starting children transitions, "afterChildren" to finish children transitions before starting this transition.

const container = {
  hidden: {
    opacity: 0,
    transition: { when: "afterChildren" }
  }
}

const item = {
  hidden: {
    opacity: 0,
    transition: { duration: 2 }
  }
}

return (
  <Frame variants={container} animate="hidden">
    <Frame variants={item} size={50} />
    <Frame variants={item} size={50} />
  </Frame>
)

#Types

#MotionValue

MotionValue is used to track the state and velocity of motion values.

The constructor for this class is marked as internal. Third-party code should not call the constructor directly or create subclasses that extend the MotionValue class.

#updateAndNotify: (v: V, render?: boolean) => void

#destroy(): void

Destroy and clean up subscribers to this MotionValue.

The MotionValue hooks like useMotionValue and useTransform automatically handle the lifecycle of the returned MotionValue, so this method is only necessary if you've manually created a MotionValue via the motionValue function.

#get(): V

Returns the latest state of MotionValue

returns: V
  • The latest state of MotionValue

#getVelocity(): number

Returns the latest velocity of MotionValue

returns: number
  • The latest velocity of MotionValue. Returns 0 if the state is nonnumerical.

#isAnimating(): boolean

Returns true if this value is currently animating.

returns: boolean

#onChange(subscription): () => void

Adds a function that will be notified when the MotionValue is updated.

It returns a function that, when called, will cancel the subscription.

When calling onChange inside a React component, it should be wrapped with the useEffect hook. As it returns an unsubscribe function, this should be returned from the useEffect function to ensure you don't add duplicate subscribers..

function MyComponent() {
  const x = useMotionValue(0)
  const y = useMotionValue(0)
  const opacity = useMotionValue(1)

  useEffect(() => {
    function updateOpacity() {
      const maxXY = Math.max(x.get(), y.get())
      const newOpacity = transform(maxXY, [0, 100], [1, 0])
      opacity.set(newOpacity)
    }

    const unsubscribeX = x.onChange(updateOpacity)
    const unsubscribeY = y.onChange(updateOpacity)

    return () => {
      unsubscribeX()
      unsubscribeY()
    }
  }, [])

  return <Frame x={x} />
}
subscription: Subscriber<V>

A function that receives the latest value.

returns: () => void

A function that, when called, will cancel this subscription.

#set(v, render): void

Sets the state of the MotionValue.

const x = useMotionValue(0)
x.set(10)
v: V

Latest value to set.

render: boolean

Whether to notify render subscribers. Defaults to true

#stop(): void

Stop the currently active animation.

#AnimationControls

Control animations on one or more components.

#set(definition): void

Instantly set to a set of properties or a variant.

// With properties
controls.set({ opacity: 0 })

// With variants
controls.set("hidden")
definition: VariantLabels | TargetAndTransition

#start(definition, transitionOverride): Promise<any>

Starts an animation on all linked components.

controls.start("variantLabel")
controls.start({
  x: 0,
  transition: { duration: 1 }
})
definition: AnimationDefinition

Properties or variant label to animate to

transitionOverride: Transition

Optional transtion to apply to a variant

returns: Promise<any>
  • A Promise that resolves when all animations have completed.

#stop(): void

Stops animations on all linked components.

controls.stop()

#EasingFunction

A function that accepts a progress value between 0 and 1 and returns a new one.

const transition = {
  ease: progress => progress * progress
}

<Frame
  animate={{ opacity: 0 }}
  transition={transition}
/>

#TargetAndTransition

An object that specifies values to animate to. Each value may be set either as a single value, or an array of values.

It may also option contain these properties:

  • transition: Specifies transitions for all or individual values.
  • transitionEnd: Specifies values to set when the animation finishes.
const target = {
  x: "0%",
  opacity: 0,
  transition: { duration: 1 },
  transitionEnd: { display: "none" }
}