惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
AI
AI
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
U
Unit 42
Vercel News
Vercel News
Stack Overflow Blog
Stack Overflow Blog
P
Proofpoint News Feed
Microsoft Security Blog
Microsoft Security Blog
The GitHub Blog
The GitHub Blog
WordPress大学
WordPress大学
Martin Fowler
Martin Fowler
博客园 - 【当耐特】
B
Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
F
Full Disclosure
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
H
Help Net Security
Recorded Future
Recorded Future
N
News and Events Feed by Topic
雷峰网
雷峰网
V
Vulnerabilities – Threatpost
Schneier on Security
Schneier on Security
aimingoo的专栏
aimingoo的专栏
S
Schneier on Security
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
O
OpenAI News
Project Zero
Project Zero
罗磊的独立博客
G
GRAHAM CLULEY
腾讯CDC
P
Privacy International News Feed
V
V2EX
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Hugging Face - Blog
Hugging Face - Blog
爱范儿
爱范儿
H
Heimdal Security Blog
L
LINUX DO - 热门话题
Forbes - Security
Forbes - Security
美团技术团队
MongoDB | Blog
MongoDB | Blog
Security Latest
Security Latest
M
MIT News - Artificial intelligence
T
Tor Project blog
Cisco Talos Blog
Cisco Talos Blog
宝玉的分享
宝玉的分享
T
Threat Research - Cisco Blogs
TaoSecurity Blog
TaoSecurity Blog

Maxime Heckel's Blog

On Rendering the Sky, Sunsets, and Planets - The Blog of Maxime Heckel Shades of Halftone - The Blog of Maxime Heckel Field Guide to TSL and WebGPU - The Blog of Maxime Heckel On Shaping Light: Real-Time Volumetric Lighting with Post-Processing and Raymarching for the Web - The Blog of Maxime Heckel Speaking at Figma Config 2025 - The Blog of Maxime Heckel Post-Processing Shaders as a Creative Medium - The Blog of Maxime Heckel On Crafting Painterly Shaders - The Blog of Maxime Heckel The Art of Dithering and Retro Shading for the Web - The Blog of Maxime Heckel Moebius-style post-processing and other stylized shaders - The Blog of Maxime Heckel Shining a light on Caustics with Shaders and React Three Fiber - The Blog of Maxime Heckel Real-time dreamy Cloudscapes with Volumetric Raymarching - The Blog of Maxime Heckel Painting with Math: A Gentle Study of Raymarching - The Blog of Maxime Heckel Building a magical AI-powered semantic search from scratch - The Blog of Maxime Heckel Beautiful and mind-bending effects with WebGL Render Targets - The Blog of Maxime Heckel Refraction, dispersion, and other shader light effects - The Blog of Maxime Heckel The magical world of Particles with React Three Fiber and Shaders - The Blog of Maxime Heckel The Study of Shaders with React Three Fiber - The Blog of Maxime Heckel Building a Design System from scratch - The Blog of Maxime Heckel Building a Vaporwave scene with Three.js - The Blog of Maxime Heckel Cubic Bézier: from math to motion - The Blog of Maxime Heckel First steps with GPT-3 for frontend developers - The Blog of Maxime Heckel Building the perfect GitHub CI workflow for your frontend team - The Blog of Maxime Heckel Migrating to Next.js - The Blog of Maxime Heckel Static Tweets with MDX and Next.js - The Blog of Maxime Heckel Advanced animation patterns with Framer Motion - The Blog of Maxime Heckel Scrollspy demystified - The Blog of Maxime Heckel The Power of Composition with CSS Variables - The Blog of Maxime Heckel My first failed SwiftUI project - The Blog of Maxime Heckel Guide to creating animations that spark joy with Framer Motion - The Blog of Maxime Heckel Using Shortcuts and serverless to build a personal Apple Health API - The Blog of Maxime Heckel SEO mistakes I've made and how I fixed them - The Blog of Maxime Heckel Going native: SwiftUI from the perspective of a React developer - The Blog of Maxime Heckel Build your own preview deployment service - The Blog of Maxime Heckel The little guide to CI/CD for frontend developers - The Blog of Maxime Heckel Immigrating to the US - The Blog of Maxime Heckel The physics behind spring animations - The Blog of Maxime Heckel Generate screenshots of your code with a serverless function - The Blog of Maxime Heckel How to use Framer Motion with Emotion styled-components - The Blog of Maxime Heckel Data Fetching with NextJS: What I learned - The Blog of Maxime Heckel Learning in public - The Blog of Maxime Heckel Fixing the dark mode flash issue on server rendered websites - The Blog of Maxime Heckel How to fix NPM link duplicate dependencies issues - The Blog of Maxime Heckel Running scheduled cross-browser end-to-end tests on Github CI - The Blog of Maxime Heckel How I built my first custom ESLint rule - The Blog of Maxime Heckel React Lazy: a take on preloading views - The Blog of Maxime Heckel Automated UI accessibility testing with Cypress - The Blog of Maxime Heckel Building a GraphQL wrapper for the Docker API - The Blog of Maxime Heckel Switching off the lights - Adding dark mode to your React app - The Blog of Maxime Heckel Getting started with Typescript on Gatsby - The Blog of Maxime Heckel Rebuilding Redux with Hooks and Context - The Blog of Maxime Heckel Asynchronous rendering with React - The Blog of Maxime Heckel Using Flow generics to type generic React components - The Blog of Maxime Heckel How to efficiently type your styled-components with Flow - The Blog of Maxime Heckel How I got started with Kubernetes on GKE - The Blog of Maxime Heckel React sub-components Part 3: Whitelisting sub-components with flow - The Blog of Maxime Heckel React sub-components Part 2: Using the new Context API - The Blog of Maxime Heckel React sub-components - The Blog of Maxime Heckel Running Golang tests with Jest - The Blog of Maxime Heckel No title No title
Everything about Framer Motion layout animations - The Blog of Maxime Heckel
Maxime Heckel · 2022-03-08 · via Maxime Heckel's Blog

Framer Motion has changed a lot since I last wrote about it. So much so that I recently got a bit lost trying to build a specific layout animation and my own blog post that actually looked into this specific type of animation was far from helpful 😅. Despite the updated section I added back in November, it still felt like I was not touching upon several points on this subject and that some of them were incomplete.

On top of the API changes and the many new features that the Framer team added to the package around layout animations, I noticed that there are lots of little tricks that can make your layout animations go from feeling clumsy to absolutely ✨ perfect ✨. However, these are a bit hidden or lack some practical examples to fully understand them.

Thus, I felt it was time to write a dedicated deep dive into all the different types of layout animations. My objective is for this article to be the place you go to whenever you need a refresher on layout animations or get stuck. Additionally, I'll give you some of my own tips and tricks that I use to work around some of the glitches that layout animations can trigger and examples on how to combine them with other tools from the library such as AnimatePresence to achieve absolutely delightful effects in your projects!

Layout animations fundamentals

Before we dive into the new features and complex examples of layout animations, let's look back at the fundamentals to reacquaint ourselves with how they work.

A brief refresher on layout animations

In Framer Motion, you can animate a motion component between distinct layouts by setting the layout prop to true. This will result in what we call a layout animation.

We can't animate a motion component between layouts using a combination of initial and animate props as we would do for other kinds of Framer Motion animations. For that, we need to use the layout prop.

In the example below, you'll find a first showcase of a layout animation:

  • You can change the position of the motion component, the square, along the x axis.

  • You can enable or disable the layout prop for that motion component

We can see that each time we change the layout, i.e. a rerender occurs, the layout prop allows for the component to transition smoothly from its previous layout to the newly selected one. However, without it there is no transition: the square will move abruptly.

Layout animations "smooth things up", and add a certain level of physicality to some user interactions where usually things would transition abruptly. One example where they can shine is when adding/removing elements from a list. I tend to leverage layout animations a lot for use cases like this one, especially combined with other Framer Motion features such as AnimatePresence.

The playground below showcases one of my own NotificationList component that leverages layout animations:

  • each notification is wrapped in a motion component with the layout prop set to true.

  • the overall list is wrapped in AnimatePresence thus allowing each item in a list to have an exit animation.

  • clicking on any of the notifications on the list will remove them and, thanks to layout animations, the stack will gracefully readjust itself.

Fixing distortions

When performing a layout animation that affects the size of a component, some distortions may appear during the transition for some properties like borderRadius or boxShadow. These distortions will occur even if these properties are not part of the animation.

Luckily, there's an easy workaround to fix those: set these properties as inline styles as showcased below:

Expand card

Set distorted properties inline

10

.box[data-expanded="true"] {

19

data-expanded={expanded}

More about the layout prop

We just saw that setting the layout prop to true gives us the ability to animate a component between layouts by transitioning any properties related to its size or position. I recently discovered that there are more values that the layout prop can take:

  • layout="position": we only smoothly transition the position-related properties. Size-related properties will transition abruptly.

  • layout="size": we only smoothly transition the size-related properties. Position-related properties will transition abruptly.

To illustrate this, I built the widget below that showcases how the transition of a motion component is altered based on the value of the layout prop:

Why would we need to use these other layout properties? What's the practical use? you may ask. Sometimes, as a result of a layout animation, the content of a component that resizes can end up "squished" or "stretched". If you see this happening when working on a layout animation, chances are that it can be fixed by simply setting the layout prop to position.

Below you'll find an example of such a use case:

  • Removing items in this horizontal list will affect the size of each component. By default, you will notice the components getting slightly squished when an item is removed.

  • Wrapping the content in a motion component and setting layout to position by toggling the switch will fix all the distortions you may observe on the content of the motion block. Each component will resize gracefully with a more natural transition.

Example of practical use case for layout="position"

2

<Label variant="success">

7

justifyContent: 'start',

These two concepts are perhaps what I struggled the most with recently as:

  • they appear to be closely related based on their names but have very distinct purposes and use cases

  • there has been a lot of API changes in this area. Thus, everything I thought I had mastered was actually brand new and a bit different 😅

And I know I'm not the only one, I've seen many people confusing shared layout animations and LayoutGroup

Shared layout animations

One might think that this is yet another type of layout animation like we saw in the previous part, but with a twist. It's not wrong, but also not quite exact either.

Shared layout animations have their own API, not directly related to the layout prop. Instead of animating a component's position and size, we are animating a component between all its instances that have a common layoutId prop. To illustrate this concept let's look at the playground below:

We can see in this example that:

  • We're transitioning between multiple instances of the Arrow component

  • They all share a common layoutId which tells Framer Motion that these components are related and need to transition from one instance to the newly "active" one when the user clicks on a new item.

The shared aspect comes from the effect of the component moving from one position to another as if it was the same. And that's what I love about shared layout animations. It's all smoke and mirrors. Like a magic trick 🪄!

The "magic" behind it is actually quite simple:

  1. In our example above, when clicking on a new element, the Arrow component that was displayed on the screen fades away to reveal a new instance of the Arrow component

  2. That new Arrow component is the one that will be eventually positioned under our newly selected element on the list

  3. That component then transitions to its final position

To show you this effect, I reused the demo above and gave a different color to each instance of Arrow so you can better visualize what's happening:

One component I like to decorate with shared layout animations is Tabs. We can leverage this type of animation to add proper transitions for the "selected indicator" but also to a "hover highlight" like Vercel does on their own Tabs component! Below is an example implementation of such component with these two layout animations:

  • We can see the "selected indicator" transitioning from one tab to another when a new one is selected

  • The "hover highlight" will follow the user's mouse when hovering over the Tabs component

  • Each shared layout animation has a distinct layoutId prop: underline and highlight

There's however one little problem. What if we wanted to build a reusable component that has a shared layout animation defined and use it twice within the same page? Well, both seemingly distinct shared layout animation would end up with the same layoutId prop which, as a result, would cause things to get a bit weird:

  • Item 1
  • Item 2
  • Item 3
  • Item 1
  • Item 2
  • Item 3

This is where LayoutGroup comes into the picture 👀.

LayoutGroup: the namespacing use case

For this use case, we can see LayoutGroup as a tool to use on top of shared layout animations and not directly related to them as it may have first seemed.

We saw above that layoutId props do not take into consideration which instance of a component they are used in, i.e. they are global. In this first use case, we'll use it to namespace our shared layout animations: give them a unique id so they can be rendered multiple times and still behave distinctly.

Namespacing multiple instance of shared layout animations with LayoutGroup

1

const ComponentsWithSharedLayoutAnimation = () => {

6

<motion.div layoutId="shared-layout-animation" />

14

<ComponentsWithSharedLayoutAnimation />

17

<ComponentsWithSharedLayoutAnimation />

By using LayoutGroup in our Tabs component implementation, we can now make it a truly reusable component and work around the bug we showcased in the previous part: the shared layout animations are now only "shared" within their own LayoutGroup.

  • Item 1
  • Item 2
  • Item 3
  • Item 1
  • Item 2
  • Item 3

1

const Tabs = ({ id }) => {

2

const [focused, setFocused]

3

= React.useState(null);

4

const [selected, setSelected]

5

= React.useState('Item 1');

LayoutGroup: the grouping use case

Namespacing shared layout animations is not the only use case for LayoutGroup. Its original purpose is actually to:

Group motion components that should perform layout animations together.

But what does that exactly mean?

We saw in the first part that a layout animation will transition a component from one layout to another when a rerender occurs. That works fantastically well for everything within the motion component with the layout prop, but what about the sibling components?

As a result of one component's layout animation, the overall layout of the page may be affected. For example when removing an item from a list, all the surrounding components will need to adapt through a transition or a resize. The problem here is that there's no way to make those other components transition smoothly as is because:

  • they are not necessarily motion components themselves

  • they are not rerendering since not interacted with

  • since they are not rerendering they are unable to perform a layout animation by themselves, even if defined.

This can be fixed by wrapping each sibling components in a motion component with the layout set to true (if the siblings were not motion components themselves already), and wrapping all the components we wish to perform a smooth transition when the overall layout changes in a LayoutGroup.

In the little widget below I showcase this by rendering two instances of a list component where each item is a motion component:

Make some coffee ☕️ List 1

Go to the gym 🏃‍♂️ List 1

Finish blog post ✍️ List 2

Build new Three.js experiences ✨ List 2

Add new components to Design System 🌈 List 2

  • Try to remove an item from the first list and notice that the items within the first list perform a smooth layout animation and that the second list, however, moves abruptly

  • Toggle LayoutGroup wrapping on and notice that now when removing an item from the first list, the second list transition smoothly to its target position.

Reorder

Drag-to-reorder items in a list where each item then smoothly moves to its final position is perhaps the best in class use case when it comes to layout animations. It's actually the first use case I thought about when I discovered layout animations in the first place a year ago.

Lucky us, the developers at Framer gave us a ready-to-use set of components to handle that specific use case with ease 🎉. They provided 2 components that we're going to use in follow-up examples:

  1. Reorder.Group where we pass our list of items, the direction of the reorder (horizontal or vertical), and the onReorder callback which will return the latest order of the list

  2. Reorder.Item where we pass the value of an item in the list

Simple examples of drag-to-reorder list using Reorder

2

const [items, setItems] = React.useState(['Item 1', 'Item 2', 'Item 3']);

15

{items.map((item) => (

17

<Reorder.Item key={item} value={item}>

With just a few lines of code, we can get a ready-to-use list with a drag-to-reorder effect! And that's not all of it:

  • Each Reorder.Item is a motion component

  • Each Reorder.Item component in the list is able, out-of-the-box, to perform layout animations

Thus it's very easy to add a lot more animations on top of this component to build a truly delightful user experience. There are, however, two little catches that I only discovered when I started working with the Reorder components 👇

Combining everything

In the playground below, you will find a more advanced example that leverages Reorder.Group and Reorder.Item along with some other aspects of layout animations that we saw earlier:

  • Build new Three.js experiences ✨

  • Add new components to Design System 🌈

Check items off the list when you're done!

  • layout="position" is used on the content of each item to avoid distortions when they are selected and a layout animation is performed

  • Custom React styled-components use Reorder components through polymorphism

8

<Card.Body as={motion.div} layout="position">

10

id={`checkbox-${item.id}`}

11

aria-label="Mark as done"

12

checked={item.checked}

13

onChange={() => completeItem(item.id)}

15

<Text>{item.text}</Text>

  • Inline styles are used for the borderRadius of the item to avoid distortions when the item resizes

  • position: relative has been added as inline style to the Reorder.Item to fix overlap issues that occur while dragging elements of the list over one another

  • AnimatePresence is used to allow for exit animations when elements are removed from the list

5

exit={{ opacity: 0, transition: { duration: 0.2 } }}

12

width: item.checked ? '70%' : '100%',

  • The list and its sibling elements are wrapped in a LayoutGroup to perform smooth layout animations when the task list updates and changes the overall layout

2

<Reorder.Group axis="y" values={items} onReorder={setItems}>

9

<span>Check items off the list when you&apos;re done!</span>

Want to run this example yourself and hack on top of it? You can find the full implementation of this example on my blog's Github repository.

Conclusion

You now know pretty much everything there is to know about Framer Motion layout animations 🎉. Whether it's for some basic use cases, such as the Notification List we've seen in the first part, adding little details like the shared layout animations from the tabs components, to building reorderable lists with complex transitions: layout animations have no more secrets to you.

I hope this blog post can serve you as a guide/helper to make your own animations look absolutely perfect ✨, especially when working on the nitty-gritty details of your transitions. It may sound overkill to spend so much time reading and working around the issues we showcased in this blog post, but trust me, it's worth it!

Want to go further?

I'd suggest taking a look at some of the complex examples provided in the Framer Motion documentation. The team came up with very good examples such as this drag to reorder tabs component which contains every concept used in the task list example that I introduced in this blog post. After that, I'd try to see where you could sprinkle some layout animation magic on your own projects 🪄. There's no better way of learning than building things by yourself!