Motion
Back to framer.com
DocumentationComponents
motion
Motion
Back to framer.com
Design and publish your first free site today.
Getting started
  • Introduction
  • Examples
Animation
  • Overview
  • Layout
  • Gestures
  • Scroll
  • Transition
Components
  • motion
  • AnimatePresence
  • LayoutGroup
  • LazyMotion
  • MotionConfig
  • Reorder
Motion values
  • Overview
  • useMotionValueEvent
  • useMotionTemplate
  • useScroll
  • useSpring
  • useTime
  • useTransform
  • useVelocity
  • useWillChange
Hooks
  • useAnimate
  • useAnimationFrame
  • useDragControls
  • useInView
  • useReducedMotion
Universal
  • animate
  • transform
  • stagger
  • Easing functions
3D
  • Introduction
  • LayoutCamera
  • LayoutOrthographicCamera
  • MotionCanvas
Guides
  • Accessibility
  • Reduce bundle size
  • Upgrade guides
Community
  • GitHub
  • Discord

Motion components

Motion components are DOM primitives optimised for 60fps animation and gestures.

There's a motion component for every HTML and SVG element, for instance motion.div, motion.circle etc.

These work exactly like their static counterparts, but offer props that allow you to:

  • Animate
  • Add drag, pan, hover and tap gestures
  • Respond to gestures and elements entering the viewport with animation
  • Deeply animate throughout React trees via variants

And much more.

#Supported values

#Value types

Motion can animate:

  • Numbers: 0, 10 etc.
  • Strings containing numbers: "0vh", "10px" etc.
  • Colors: Hex, RGB, HSLA.
  • Complex strings containing multiple numbers and/or colors (ie "10px 0 #000")

When animating to a non-animatable value like "block", this value will be set instantly. By setting this value within transitionEnd, this value will be set at the end of the animation.

<motion.div
animate={{
x: 0,
backgroundColor: "#000",
boxShadow: "10px 10px 0 rgba(0, 0, 0, 0.2)",
position: "fixed",
transitionEnd: {
display: "none",
},
}}
/>

#Value type conversion

In general, values can only be animated between two of the same type (ie two px, two % etc).

However, HTML component's x, y, width, height, top, left, right and bottom values have enhanced support and can all be animated freely between different value types.

<motion.div
initial={{ x: "100%" }}
animate={{ x: "calc(100vw - 50%)" }}
/>

Additionally, any color type (hex, HSL, RGB) can animate between each other.

#Transform

Transform properties are accelerated by the GPU, and therefore animate smoothly. They can be set and animated individually as:

  • Translate shortcuts: x, y, z
  • Translate: translateX, translateY, translateZ
  • Scale: scale, scaleX, scaleY
  • Rotate: rotate, rotateX, rotateY, rotateZ
  • Skew: skew, skewX, skewY
  • Perspective: transformPerspective

motion components have enhanced style props, allowing you to set them individually there, too.

<motion.a
whileHover={{ scale: 1.2 }}
whileTap={{ scale: 0.8 }}
style={{ x: 100 }}
/>

For convenience, transform values are applied in a specific order: translate, scale, rotate, skew.

However, you can customize this default order using the transformTemplate prop.

function template({ rotate, x }) {
return `rotate(${rotate}) translateX(${x})`
}
return (
<motion.div
transformTemplate={template}
animate={{ rotate: 360 }}
style={{ rotate: 0, x: "calc(50vh - 100px)" }}
/>
)

SVG note: For SVG components, x and y attributes (as opposed to the transform style) can be set using attrX and attrY within animation props.

#Transform origin

transform-origin has three shortcut values that can be set and animated individually:

  • originX
  • originY
  • originZ

If set as numbers, originX and Y default to a progress value between 0 and 1. originZ defaults to pixels.

<motion.div style={{ originX: 0.5 }} />

#CSS variables

Motion can animate the value of CSS variables, and also read CSS variables as animation targets.

#Using pre-defined CSS variables in animation

HTML motion components can animate to and from CSS variables, as long as that variable is defined on a component ancestor.

<motion.li animate={{ background: "var(--action)" }} />

#Animating CSS variables

By defining and animating CSS variables, we can use a parent motion component to declaratively animate multiple DOM children.

When animating CSS variables in TypeScript, the prop will need to be cast as any to prevent type errors (as there's an infinite number of variable names).

CSS variables are also of an arbitary type, so Motion can't infer their default type. You're able to animate rotate as a number because Motion understands that it should be set as deg, whereas '--rotate' needs to be explicitly set with the unit type, e.g. '360deg'.

<motion.ul
initial={{ '--rotate': '0deg' } as any}
animate={{ '--rotate': '360deg' } as any}
transition={{ duration: 2, repeat: Infinity }}
>
<li style={{ transform: 'rotate(var(--rotate))' }} />
<li style={{ transform: 'rotate(var(--rotate))' }} />
<li style={{ transform: 'rotate(var(--rotate))' }} />
</motion.ul>

#SVG line drawing

Line drawing animations can be created with many SVG elements using three special properties: pathLength, pathSpacing and pathOffset.

These are all set as a value between 0 and 1, where 1 is the measured length of the path.

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

#Custom components

Any component can be turned into a motion component by wrapping it with the motion() function.

The provided component must forward ref to the DOM element you want to animate.

In addition, motion() must not be called inside a React render function.

const Component = React.forwardRef((props, ref) => (
<div ref={ref} />
))
const MotionComponent = motion(Component)

It's also possible to pass strings to motion, which will create custom DOM elements.

// Will render <custom-element /> into HTML
const MotionComponent = motion('custom-element')

By default, all motion props (like animate etc) are filtered out of the props forwarded to the provided component. By providing a forwardMotionProps config, the provided component will receive these props.

motion(Component, { forwardMotionProps: true })

#Performance

Motion animates values outside the React render cycle for increased performance.

Using MotionValues instead of state to update visual properties will also avoid re-renders.

Where possible, animate just transform values and opacity, as they are GPU-accelerated. This way, you can animate hundreds of layers on modern mobile devices.

// GPU accelerated (fast)
<motion.div style={{ x: 0 }} animate={{ x: 100 }} />
// CPU drawing (slower)
<motion.div style={{ left: 0 }} animate={{ left: 100 }} />

#Server-side rendering

motion components are fully compatible with server-side rendering, meaning the initial state of a component will be reflected in the server-generated output.

// Server will output `translateX(100px)`
<motion.div initial={false} animate={{ x: 100 }} />

#Exceptions

The following SVG values are not currently compatible with server-side rendering: scale, rotate, pathLength, pathOffset and pathSpacing.

scale and rotate rely on the dynamic calculation of transformOrigin - originX and originY should be set as strings (either px or %) to support these server side.

<motion.circle
style={{ scale: 2, originX: "100px", originY: "100px" }}
/>

path values rely on the measurement of the overall path length. Setting strokeDasharray to "0 1" will hide the path until Motion can measure it.

<motion.path strokeDasharray="0 1" />

#Props

Note: Additional props can be found on the gestures and scroll animation pages.

#Animation

#initial: boolean | Target | VariantLabels

Properties, variant label or array of variant labels to start in.

Set to false to initialise with the values in animate (disabling the mount animation).

// As values
<motion.div initial={{ opacity: 1 }} />
// As variant
<motion.div initial="visible" variants={variants} />
// Multiple variants
<motion.div initial={["visible", "active"]} variants={variants} />
// As false (disable mount animation)
<motion.div initial={false} animate={{ opacity: 0 }} />

#animate: AnimationControls | TargetAndTransition | VariantLabels | boolean

Values to animate to, variant label(s), or AnimationControls.

// As values
<motion.div animate={{ opacity: 1 }} />
// As variant
<motion.div animate="visible" variants={variants} />
// Multiple variants
<motion.div animate={["visible", "active"]} variants={variants} />
// AnimationControls
<motion.div animate={animation} />

#exit: TargetAndTransition | VariantLabels

A target to animate to when this component is removed from the tree.

This component must be the first animatable child of an AnimatePresence to enable this exit animation.

This limitation exists because React doesn't allow components to defer unmounting until after an animation is complete. Once this limitation is fixed, the AnimatePresence component will be unnecessary.

import { AnimatePresence, motion } from 'framer-motion'
export const MyComponent = ({ isVisible }) => {
return (
<AnimatePresence>
{isVisible && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
)}
</AnimatePresence>
)
}

#transition: Transition

Default transition. If no transition is defined in animate, it will use the transition defined here.

const spring = {
type: "spring",
damping: 10,
stiffness: 100
}
<motion.div transition={spring} animate={{ scale: 1.2 }} />

#variants: Variants

Variants allow you to define animation states and organise them by name. They allow you to control animations throughout a component tree by switching a single animate prop.

Using transition options like delayChildren and staggerChildren, you can orchestrate when children animations play relative to their parent.

After passing variants to one or more motion component's variants prop, these variants can be used in place of values on the animate, initial, whileFocus, whileTap and whileHover props.

const variants = {
active: {
backgroundColor: "#f00"
},
inactive: {
backgroundColor: "#fff",
transition: { duration: 2 }
}
}
<motion.div variants={variants} animate="active" />

#style: MotionStyle

The React DOM style prop, enhanced with support for MotionValues and separate transform values.

export const MyComponent = () => {
const x = useMotionValue(0)
return <motion.div style={{ x, opacity: 1, scale: 0.5 }} />
}

#Layout animation

#layout: boolean | "position" | "size"

If true, this component will automatically animate to its new position when its layout changes.

This will perform a layout animation using performant transforms. Part of this technique involved animating an element's scale. This can introduce visual distortions on children, boxShadow and borderRadius.

To correct distortion on immediate children, add layout to those too.

boxShadow and borderRadius will automatically be corrected if they are already being animated on this component. Otherwise, set them directly via the initial prop.

If layout is set to "position", only its position will animate. This is good for text components that don't often look good when stretched.

If layout is set to "size", only its size will animate.

#layoutId: string

When a component with a layoutId is removed from the React tree, and then added elsewhere, it will visually animate from the previous component's bounding box and its latest animated values.

If the previous component remains in the tree it will crossfade to the new one.

{items.map(item => (
<motion.li layout>
{item.name}
{item.isSelected && <motion.div layoutId="underline" />}
</motion.li>
))}

#layoutDependency: any

Layout changes are, by default, detected every render. To improve performance, you can hint when layout changes are likely to take place by passing a value to layoutDependency.

The motion component will then only measure itself when the passed value changes, or if the layoutDependency of another motion component within the same LayoutGroup changes.

#layoutScroll: boolean

For layout animations to work correctly within scrollable elements, their scroll offset needs measuring. For performance reasons, Framer Motion doesn't measure the scroll offset of every ancestor. Add the layoutScroll prop to elements that should be measured.

<motion.div layoutScroll style={{ overflow: "scroll" }}>
<motion.div layout />
</motion.div>

#onLayoutAnimationStart(): void

A callback that will fire when a layout animation on this component starts.

#onLayoutAnimationComplete(): void

A callback that will fire when a layout animation on this component completes.

#Animation events

#onUpdate(latest): void

Callback with latest motion values, fired max once per frame.

latest: ResolvedValues

function onUpdate(latest) {
console.log(latest.x, latest.opacity)
}
<motion.div animate={{ x: 100, opacity: 0 }} onUpdate={onUpdate} />

#onAnimationStart(): void

Callback when animation defined in animate begins.

function onStart() {
console.log("Animation started")
}
<motion.div animate={{ x: 100 }} onAnimationStart={onStart} />

#onAnimationComplete(definition): void

Callback when animation defined in animate is complete.

The provided callback will be called the triggering animation definition. If this is a variant, it'll be the variant name, and if a target object then it'll be the target object.

This way, it's possible to figure out which animation has completed.

definition: AnimationDefinition

function onComplete() {
console.log("Animation completed")
}
<motion.div
animate={{ x: 100 }}
onAnimationComplete={definition => {
console.log('Completed animating', definition)
}}
/>

#Gestures

Motion extends the basic set of event listeners provided by React with a simple yet powerful set of UI gesture recognisers.

Learn more

#Advanced

#inherit: boolean

Set to false to prevent inheriting variant changes from its parent.

#custom: any

Custom data to use to resolve dynamic variants differently for each animating component.

const variants = {
visible: (custom) => ({
opacity: 1,
transition: { delay: custom * 0.2 }
})
}
<motion.div custom={0} animate="visible" variants={variants} />
<motion.div custom={1} animate="visible" variants={variants} />
<motion.div custom={2} animate="visible" variants={variants} />

#transformTemplate(transform, generatedTransform): string

When animating independent transforms like x, scale etc, Motion generates a transform style with these transforms in a intuitive order.

transformTemplate can be used to create a different order, or to append/preprend the automatically generated transform property.

transform: TransformProperties

The latest animated transform props

generatedTransform: string

The transform string as automatically generated by Framer Motion

returns: string

<motion.div
style={{ x: 0, rotate: 180 }}
transformTemplate={
({ x, rotate }) => `rotate(${rotate}deg) translateX(${x}px)`
}
/>

Note: transformTemplate only applies to independent transforms. It has no effect when animating transform directly.

<motion.div
animate={{ transform: "translateX(100px)" }}
// No effect!
transformTemplate={
({ x, rotate }) => `rotate(${rotate}deg) translateX(${x}px)`
}
/>
PreviousTransitionNextAnimatePresence
On this page
  • Supported values
  • Value types
  • Value type conversion
  • Transform
  • Transform origin
  • CSS variables
  • Custom components
  • Performance
  • Server-side rendering
  • Props
  • Animation
  • Layout animation
  • Animation events
  • Gestures
  • Advanced

Copyright © 2022 Framer B.V.

  • Security
  • Terms of Service
  • Privacy Statement