abstract background image

Layout Animation basics with Framer Motion

Published on ยท 5 min read

Framer Motion provides a lot of powerful tools that require minimum effort to use. I've used it for a couple of years now both in my professional work and also a lot in my hobby projects. I recently got to implement some layout animations at work, and I found it fascinating how easy it was to achieve so much with so little code. So I thought it would make a great blog post!

In this post we will focus on one of Framer Motions many powerful features - the layout prop. We will learn about how we can use it to achieve smooth layout animations with ease.

What is layout animations, and why do I need them?

Layout animations can be a great when you have an application UI where your components may be removed, switched places, added or resized. Without any animation your components will just show up in their own positions without any indication of where they came from, or where they are going. This might confuse users as to what actually happening. Layout animations can be used to guide the users attention to what is happening to the elements.

When we talk about layout animations we are referring to changes to any of the following properties:

  • Positions - grid, flex or position
  • Size properties - width or height
  • Position of elements - adding / removing an item from a list of items

Layout animation basics

With Framer Motion we can animate any motion component between different layouts by applying the layout prop to the element. Now the element will automatically animate to any layout changes resulting from any re-renders.

Some practical examples of when this would be happning:

  • Adding / removing items in a list of items
  • The width of an item changing due to some additional data being added / removed
  • The sorting of a list is reversed and we change flex-start to flex-end

Let's take a look at a basic example where we can change the justify-self property on a simple square div.

1import React from 'react';
2import { motion } from 'framer-motion';
3
4type Props = {
5 position: 'start' | 'center' | 'end'
6}
7
8const PositionExample: React.FC<Props> = ({ position }) => (
9 <div
10 style={{ justifySelf: position }}
11 />
12);
13
14export default PositionExample;

This is how easy it is to get started with layout animations using Framer Motion. The only thing we really needed to do was to add the layout prop the the motion element and we get this smooth transition between different positions.

By adding this kind of animation to your UI you can help your user to follow what is happening on the screen and make elements move around more naturally.

Next we will take a look at another example that might be more similiar to something you'd might encouter in your own applications. We are going to look at a simple list component and see how we can leverage layout animations to help the user understand the actions taken when interacting with the list.

We will also introduce the AnimatePresence component from Framer Motion. AnimatePresence allows us to animate an unmounting component, so when we remove it from the list we can give it a nice "fade out" effect.

  • Apples ๐ŸŽ
  • Bread ๐Ÿฅ–
  • Cheese ๐Ÿง€
  • Eggs ๐Ÿฅš
  • Cookies ๐Ÿช
1import React from 'react';
2import { motion, AnimatePresence } from 'framer-motion';
3
4const INITIAL_STATE = [
5 'Apples ๐ŸŽ',
6 'Bread ๐Ÿฅ–',
7 'Cheese ๐Ÿง€',
8 'Eggs ๐Ÿฅš',
9 'Cookies ๐Ÿช',
10 ];
11
12const SimpleList: React.FC = () => {
13 const [items, setItems] = React.useState(INITIAL_STATE);
14
15 const onClickItem = (task: string) => {
16 setItems(items.filter((item) => item !== task));
17 };
18
19 const onClickRefresh = () => {
20 setItems(INITIAL_STATE);
21 };
22
23 return (
24 <ul>
25 <AnimatePresence>
26 {items.map((item) => (
27 <motion.li
28 key={item}
29 onClick={() => onClickItem(item)}
30 layout
31 exit={{ opacity: 0 }}
32 >
33 {item}
34 </motion.li>
35 ))}
36 </AnimatePresence>
37 </ul>
38 );
39 };
40
41 export default SimpleList;

That was a little more code than the previous example! However in terms of code related to animations, we did not actually add that much. Let's try and break it down.

  • We wrapped out list elements in an AnimatePresence component. This allows us to access the exit prop on the motion element. The exit prop is what we use to animate when a component is unmounting. Giving it a value of opacity: 0 will create the fade-out effect when we remove an item from the list.
  • We are still using the layout prop on the motion elements. This is what allows each list item to smoothly transition to it's new position after an item is removed from the list.

Diving deeper into the layout prop

Now we know how we can use the layout prop to enable smooth transitions for layout animations. But in some more advanced use-cases you might find that your content will look distorted or squished during the animation transition.

Let's take a look at a real world example of this happening. Let's imagine we have a couple of <Badge /> components that acts as some type of filters on a shopping website.

  • Label 1
  • Label 2
  • Label 3
1import React from 'react';
2import { motion } from 'framer-motion';
3
4const BadgesExample: React.FC = () => (
5 <ul>
6 {filters.map((filter) => (
7 <motion.li key={filter} style={{ width: '100%' }} layout>
8 <Badge>
9 <div
10 style={{
11 width: '100%',
12 display: 'flex',
13 alignItems: 'center',
14 }}
15 >
16 <CloseButton />
17 <span>{filter}</span>
18 </div>
19 </Badge>
20 </motion.li>
21 ))}
22 </ul>
23);
24
25export default BadgesExample;

What happens is that when we remove a Badge from the list will change the size of each Badge, so when we only use layout=true we are telling Framer Motion to animate both the size and the position of the element. This is not always what you want. Luckily we can tell the component explicitly that we only want to animate the position of the component.

Conclusion

We have now learned the basics of how to use the layout prop to achieve smooth layout animations for our components. Although this might have been a basic introduction, I hope it may serve as a helper to get you interested in diving deeper into Framer Motion and all the things you can do with the library! ๐ŸŽ‰

Looking for more?

If I have sparked your interest for Framer Motion and wondering what else is possible, make sure to check out their documentation. Also, make sure to check out this really cool example of how to achieve this "drag to re-order" tabs component! Super cool stuff!