Want to build websites in no-time? Announcing the new Framer Beta.Learn more
Framer
DocumentationMotion resources
Upgrade guides
  • Overview
  • Motion
  • Handshake
  • Guides
  • API Documentation
Want to build websites in no-time? Announcing the new Framer Beta.Learn more
Framer
  • Teams
  • Showcase
  • Developers
  • Resources
    • Tutorials
    • Examples
    • Components
    • Templates
    • Sessions
    • Support
    • Updates
  • Blog
  • Pricing
  • ···
    • Blog
    • Pricing
DocumentationMotion resources
Upgrade guides
  • Overview
  • Motion
  • Handshake
  • Guides
  • API Documentation
Getting started
  • Introduction
  • Examples
API
  • Animation
  • Transition
  • Gestures
  • MotionValue
  • Utilities
Components
  • motion
  • AnimatePresence
  • LayoutGroup
  • LazyMotion
  • MotionConfig
  • Reorder
3D
  • Introduction
  • LayoutCamera
  • LayoutOrthographicCamera
  • MotionCanvas
Motion resources
  • Accessibility
  • Reduce bundle size
  • Upgrade guides
Code in Framer
  • Utilities
  • RenderTarget
  • Property Controls
Community
  • GitHub
  • Discord

Upgrade guides

How to upgrade to the latest version of Framer Motion

#6.0

Framer Motion 3D now lives in the framer-motion-3d package. So to upgrade to 6.0 simply change imports from "framer-motion/three" to "framer-motion-3d".

#5.0

#Shared layout animations

Framer Motion 5 removes the AnimateSharedLayout component.

Now, you can use the layoutId prop and components will animate from one to another without the need for the AnimateSharedLayout wrapper.

#Measuring layout changes

Layout changes are detected when a component with a layout or layoutId prop re-renders. But it isn't performant to measure all components when just one changes.

AnimateSharedLayout could be used to group components that affected each other's layout. When one rerendered, AnimateSharedLayout would force them all to rerender.

This was not a performant approach because all grouped components would perform a re-render. Now, components that affect each other's layout can be grouped with LayoutGroup:

import { LayoutGroup, motion } from "framer-motion"
export function App() {
return (
<LayoutGroup>
<Submenu />
<Submenu />
</LayoutGroup>
)
}
function Submenu({ children }) {
const [isOpen, setIsOpen] = useState(false)
return (
<motion.ul
layout
style={{ height: isOpen ? "auto" : 40 }}
>
{children}
</motion.ul>
)
}

Grouped components will be measured whenever one of them renders, but they won't be forced to render themselves.

#Scoped layout animations

Previously, because AnimateSharedLayout was required, it would naturally scope shared layout animations. So animating between components with the same layoutId would only happen within the same AnimateSharedLayout:

/**
* These items share the same layoutId but won't animate
* between each other because they're children of different
* AnimateSharedLayout components.
*/
<AnimateSharedLayout>
{isVisible ? <motion.div layoutId="modal" /> : null}
</AnimateSharedLayout>
<AnimateSharedLayout>
{isVisible ? <motion.div layoutId="modal" /> : null}
</AnimateSharedLayout>

This could lead to very poor performance. AnimateSharedLayout reduces layout thrashing within itself by batching layout measurements. But it had no way of batching between many AnimateSharedLayout components. The more you add, the more layout thrashing will occur.

Now, there is one global tree throughout your app so all layout measurements are batched. But this means all layoutIds share the same global context. To bring back this old behaviour you can namespace layoutId by providing a id prop to LayoutGroup:

/**
* These layoutIds are now namespaced with
* the id provided to LayoutGroup.
*/
<LayoutGroup id="a">
{isVisible ? <motion.div layoutId="modal" /> : null}
</LayoutGroup>
<LayoutGroup id="b">
{isVisible ? <motion.div layoutId="modal" /> : null}
</LayoutGroup>

#Drag to reorder

Previous drag-to-reorder implementations were ad-hoc, usually adapted from an old proof-of-concept sandbox that relied on the (now removed) onViewportBoxUpdate prop. These solutions should be reimplemented with the new Reorder components.

#ESM and create-react-app

To enable our new Handshake features, that allow you to publish no-code components straight from Framer into production, we've moved Framer Motion to ESM modules. Some build environments like create-react-app might have some trouble mixing ES modules (like Framer Motion) and CJS modules (like React).

To fix, either upgrade to create-react-app@next, or downgrade to framer-motion@4.1.17.

#4.0

Framer Motion 4 introduces a brand new LazyMotion component to help reduce bundle size.

Previously, a subset of motion functionality could be loaded in synchronously or asynchronously via MotionConfig's features prop. This functionality has been removed in favour of the new LazyMotion component.

Check out the new reduce bundle size guide to find out how to use this new API.

import { LazyMotion, domAnimation, m } from "framer-motion"
export const MyComponent = ({ isVisible }) => (
<LazyMotion features={domAnimation}>
<m.div animate={{ opacity: 1 }} />
</LazyMotion>
)

#Other breaking changes

4 also removes motion.custom(), which was previously deprecated in favour of motion().

motion.custom() had the default behaviour of forwarding all of Framer Motion's props to the underlying component. To replicate this, the forwardMotionProps option can be used.

const MotionComponent = motion(Component, {
forwardMotionProps: true
})

#3.0

Framer Motion 3 is major release but the type of breaking change is very specific and very small. It's unlikely, though possible, to change the way your animations function.

#The changing behaviour

Motion 3 features a centralisation of how animation states are computed.

All animation props are now ranked in terms of priority (left being lowest, right being highest).

When one of those props changes, or becomes active/inactive, we will recompute the necessary animations. This is an extension and codification of a behaviour that was partially implemented only for the while props, leading to a more consistent and predictable experience.

const priority = ["animate", "while-", "exit"]

#Multi-variant props

Before, only animate could accept a list of variants.

<motion.div animate={["active", "warning"]} />

Now, all animation props can.

<motion.div whileHover={["hover", "secondary"]} />

#Removing animation values

Before, if a value was outright removed from an animation prop, nothing would happen.

Now, if a value is removed, we check for it in the next highest-priority animation state. For instance, if opacity is removed from whileHover, Motion will check for it in animate and animate to that.

If we don't find one in animate, it'll check in style, or fallback to its initially-recorded value (for instance if the value was initially read from the DOM because none was explicitly defined).

#That's all!

These are subtle changes that will probably not affect the majority of projects, but they're worth being aware of.

Motion 3 seems much smaller in scope than 2, and it is! But it provides a much stronger base for variants and animation props going forward.

#2.0

Framer Motion 2 is major release and that means there's API changes. In this guide we'll take a look at how you can upgrade your code to ensure it continues to work as expected, and highlight some features that will be broken in the new version of Motion.

#Layout animations

Framer Motion 1 supported a couple of ways to perform layout animations, the positionTransition and layoutTransition props.

// Before
<motion.div layoutTransition />

In Framer Motion 2, these have both been superseded by the layout prop.

// After
<motion.div layout />

Both of the old props used to take a transition as an argument.

// Before
<motion.div layoutTransition={{ duration: 2 }} />

Now, layout animations use the same default transition prop as other animations.

// After
<motion.div layout transition={{ duration: 2 }} />

In Framer Motion 1, layout animations could distort borderRadius and boxShadow properties on components that were changing size. This is now fixed if either property is animated.

<motion.div layout initial={{ borderRadius: 20 }} />

Layout animations that changed size could also distort child components. This can now be corrected by providing them with a layout prop, too.

Only immediate children will need to be corrected for scale.

<motion.div layout>
<motion.div layout />
</motion.div>

#Breaking changes

There are some changes that don't have an immediate fix that you should be aware of before upgrading.

#Drag

Drag has been refactored to use the same layout projection rendering methodology that powers Motion 2's layout animations to ensure the two features are fully compatible with each other.

This has lead to some breaking changes:

  • Drag listeners (like onDrag) now report the point relative to the viewport, moving in line with other pointer gestures in Motion.
  • dragOriginX and dragOriginY have been removed. These were added to allow a hacky way to make positionTransition compatible with drag, but layout is compatible with drag by default.

#useAnimatedState

The useAnimatedState API was an experimental and undocumented API for use in Framer X. This has now been removed.

PreviousReduce bundle sizeNextUtilities
On this page
  • 6.0
  • 5.0
  • Shared layout animations
  • Measuring layout changes
  • Scoped layout animations
  • Drag to reorder
  • ESM and create-react-app
  • 4.0
  • Other breaking changes
  • 3.0
  • The changing behaviour
  • Multi-variant props
  • Removing animation values
  • That's all!
  • 2.0
  • Layout animations
  • Breaking changes

Framer

  • Teams
  • Pricing
  • Showcasenew
  • Blog
  • Developers
  • Updates

Platforms

  • Web
  • macOS
  • Windows
  • iOS
  • Android

Learn

  • Tutorials
  • Examples
  • Templates
  • Sessions

Resources

  • Components
  • Input Kit
  • State of Prototyping
  • Desktop Prototyping
  • Prototyping Tool
  • Mockup Tool
  • Wireframing Tool
  • UI/UX Design Tool
  • Graphic Design Tool
  • User Testing

About

  • Loupe
  • Community
  • Company
  • Careers
  • Legal

Support

  • Using Framer
  • Accounts
  • Contact

  • Twitter
  • Discord
  • Dribbble

Copyright © 2022 Framer B.V.

  • Security
  • Terms of Service
  • Privacy Statement