Getting Started with React Animations
Tags: animation, react, tutorial, webdev
Published: 2020-09-08 20:03:43

---
title: Getting Started with React Animations
published: true
description: Learn the basics of animation in React using Framer Motion. We'll focus on learning about motion components, mount and unmount animations, orchestration, dragging, and automatic animations.
tags: Animation, React, Tutorial, WebDevelopment
cover_image: https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599595357/getting-started-with-react-animations/framer-motion-6_jiyfrv.png
---

Interaction plays a key role in shaping the experience a user has on an application. Animations help define these interactions since the user's eyes tend to pay attention to moving objects. These catchy and moving elements tell a story that helps the application differentiate from competitors and bring a better user experience. 

Creating animations can be daunting, especially programming and handling orchestrations (how these coordinate between each other). Thankfully, amazing people have created abstractions in libraries that allow the developer to create seamless, hardware-accelerated animations efficiently.

In this post, I will give an introduction to Framer Motion and create simple animations with it. We'll be learning about motion components, orchestration, dragging, and automatic animations.

## React Animation Libraries

In React, we have two main animation libraries: [React Spring](https://www.react-spring.io/) and [Framer motion](https://www.framer.com/motion/). I like both of them, but I believe each one has a use case. 

React Spring is a spring-physics based animation library. These animations emulate real spring physics for smooth animations. It is really powerful and flexible. Almost all properties of HTML tags can be fully animated with React Spring. This is especially important for complex and SVG animations, however, Its main disadvantage is its high learning curve.    

Framer Motion is a motion library.  It is easy to learn and powerful with orchestrations. Contrary to React Spring, it has more types of animations: spring, tween, and inertia. Tween represent duration based animations like CSS, and inertia decelerates a value based on its initial velocity, usually used to implement inertial scrolling.

Framer Motion is perfect for handling animations on 99% of sites. Its main disadvantage is its lack of documentation and some properties won't work for SVG animations. 

Choosing between these libraries depends greatly on what you are building and how much you are willing to devote to learning animations. React Spring can do all that Framer Motion does with more flexibility, but it is harder to read and understand. I recommend it for custom, complex animations especially for SVG and 3D ([Three.js](https://threejs.org/)). 

For most websites, Framer Motion is better since it can handle most common cases and its learning curve is really low compared to React Spring. Also, its way of handling animations is more intuitive and declarative. This is why we'll focus on this library and learn about animations with it. The fundamentals of Framer Motion will be transferable to React Spring, however its syntax will be more abstract.   

## How It Works: Motion components

Framer motion core API is the `motion` component. There's a `motion` component for every HTML and SVG element. They work exactly the same as their HTML counterparts but have extra props that declaratively allow adding animations and gestures.

Think of `motion` component as a big JavaScript object that can be used to access all HTML elements. Here are some ways one would call a `motion` component: 

```jsx
<motion.div />
<motion.span />
<motion.h1 />
<motion.svg />
...
```

As said before, they allow for extra props. Some of the most used are: 

* `initial` defines the initial state of an element.
* `style` defines style properties just like normal React elements, but any change in the values through motion values (values that track the state and the velocity of the component) will be animated.
* `animate` defines the animation on the component mount. If its values are different from `style` or `initial`, it will automatically animate these values. To disable mount animations `initial` has to be set to `false`.
* `exit` defines the animation when the component unmounts. This works only when the component is a child of the `<AnimatePresence />` component.
* `transition` allows us to change animation properties. Here one can modify the duration, easing, type of animation (spring, tween, and inertia), duration, and many other properties.
* `variants` allows orchestrating animations between components.

Now that we know the basic props that `motion` can contain and how to declare them, we can proceed to create a simple animation. 

## Mount Animations

Let's say we want to create an element that on mount will fade in down. We would use the `initial` and `animate` prop.

Inside the `initial` property, we'll be declaring where the component should be located before it mounts. We'll be adding an `opacity: 0` and `y: -50`. This means the component initially will be hidden and will be 50 pixels up from its location. 

In the `animate` prop, we have to declare how the component should look when it is mounted or shown to the user. We want it to be visible and located on its initial position, so we'll add an `opacity: 1` and `y: 0`. 

Framer Motion will automatically detect that the `initial` prop has a different value from the `animate`, and animate any difference in properties. 

Our snippet will look like this:

```jsx
import { motion } from "framer-motion"

<motion.div
  initial={{ opacity: 0, y: -50 }}
  animate={{ opacity: 1, y: 0 }}  
>
  Hello World!
</motion.div>
```

This will create the following animation: 

![Card fading down](https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599544841/getting-started-with-react-animations/4_chpipj.gif)

Congratulations on creating your first animation with Framer Motion!

> 💡 You may have noticed that styles are missing from the snippets above. Some of the snippets will lack the styles in order to focus on Framer Motion's functionality.
>
> 📕 All animations in this post will have their own Storybook. [Here is the link](https://framer-animations.netlify.app/?path=/story/simple-fade-in-down-card--main) of the latter.

## Unmount Animations

Unmounting or exit animations are crucial when creating dynamic UIs, especially when deleting an item or handling page transitions. 

To handle exit animations in Framer Motions, the first step is to wrap the element or elements in an `<AnimatePresence/>`. This has to be done because:

* There is no lifecycle method that communicates when a component is going to be unmounted
* There is no way to defer unmounting until an animation is complete.

Animate presence handles all this automatically for us. 

Once the elements are wrapped, they must be given an `exit` prop specifying their new state. Just like `animate` detects a difference in values in `initial`, `exit` will detect the changes in `animate` and animate them accordingly.

Let's put this into practice! If we take the previous component and were to add an exit animation. We want it to exit with the same properties as it did in initial

```jsx
import { motion } from "framer-motion"

<motion.div
	exit={{ opacity: 0, y: -50 }}
  initial={{ opacity: 0, y: -50 }}
  animate={{ opacity: 1, y: 0 }}  	
>
  Hello World!
</motion.div>
```

Now, let's add a `<AnimatePresence/>` so it can detect when our component unmounts: 

```jsx
import { motion } from "framer-motion"

<AnimatePresence>
	<motion.div
		exit={{ opacity: 0, y: -50 }}
	  initial={{ opacity: 0, y: -50 }}
	  animate={{ opacity: 1, y: 0 }}  	
	>
	  Hello World!
	</motion.div>
</AnimatePresence>
```

Let's see what happens when the component unmounts:

![Card fading up](https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599544924/getting-started-with-react-animations/ezgif.com-gif-maker_y4hp1t.gif)

> 📕 [Storybook Link](https://framer-animations.netlify.app/?path=/story/simple-fade-out-up--main)

## Orchestration

One of Framer Motion's strong suits is its ability to orchestrate different elements through variants. Variants are target objects for simple, single-component animations. These can propagate animations through the DOM, and through this allow orchestration of elements.

Variants are passed into `motion` components through the `variants` prop. They normally will look like this: 

```jsx
const variants = {
  visible: { opacity: 0, y: -50 },
  hidden: { opacity: 1, y: 0 },
}

<motion.div initial="hidden" animate="visible" variants={variants} />
```

These will create the same animation as we did above. You may notice we passed to `initial` and `animate` a string. This is strictly used for variants. It tells what keys Framer Motion should look for inside the variants object. For the `initial`, it will look for 'hidden' and for `animate` 'visible'.

The benefit of using this syntax is that when the motion component has children, **changes in the variant will flow down through the component hierarchy**. It will continue to flow down until a child component has its own `animate` property.

Let's put this into practice! This time we will create a staggering list. Like this: 

![Card entering one after another.](https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599545055/getting-started-with-react-animations/ezgif.com-gif-maker_1_t2fae2.gif)

In the image, each item has an increasing delay between each other's entrance. The first one will enter in 0 seconds, the second in 0.1 seconds, the third in 0.2, and it will keep increasing by 0.1.

To achieve this through variants, first, let's create a variants object where we'll store all possible states and transition options:

```jsx
const variants = {
  container: {  
  },
  card: { 
  }
};
```

`variants.container` and `variants.card` represent each `motion` component we'll have. 

Let's create the animations for the cards. We see that the cards go from left to right while fading in. This means we have to update its `x` position and `opacity`.

As aforementioned, variants can have different keys for their animation states, however, we will leave it as `initial` and `animate` to indicate before mount and after mount, respectively. 

On `initial`, our component will be 50 pixels to the left and its opacity will be 0. 

On `animate`, our component will be 0 pixels to the left and its opacity will be 1. 

Like this:

```jsx
const variants = {
  container: {
  },
  card: {
    initial: {
      opacity: 0,
      x: -50
    },
    
    animate: {
      opacity: 1,
      x: 0
    }
  }
};
```

Next, we have to add the stagger effect to each of these cards. To achieve this we have to add the `container.transition` property which allows us to update the behavior of our animation. Inside the property, we'll add a `staggerChildren` property that defines an incremental delay between the animation of the children. 

```jsx
const variants = {
  container: {
		animate: {
      transition: {
        staggerChildren: 0.1
      }
    }
  },
  card: {
    initial: {
      opacity: 0,
      x: -50
    },
    
    animate: {
      opacity: 1,
      x: 0
    }
  }
};
```

Now, if we hook this variant to the `motion` components:

```jsx
import { motion } from "framer-motion";

const variants = {
  container: {
    animate: {
      transition: {
        staggerChildren: 0.1
      }
    }
  },
  card: {
    initial: {
      opacity: 0,
      x: -50
    },
    
    animate: {
      opacity: 1,
      x: 0
    }
  }
};

const StaggeredList = () => {
  return (
    <motion.div
      initial="initial"
      animate="animate"
      variants={variants.container}     
    >
      {new Array(5).fill("").map(() => {
        return <Card />;
      })}
    </motion.div>
  );
};

const Card = () => (
  <motion.div
    variants={variants.card}   
  >
    Hello World!
  </motion.div>
);
```

With this, our animation is complete and sleek staggered list ready!

![Card entering one after another.](https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599545055/getting-started-with-react-animations/ezgif.com-gif-maker_1_t2fae2.gif)

> 📕 [Storybook Link](https://framer-animations.netlify.app/?path=/story/orchestration-staggered-list--main)

## Dragging

Dragging is a feature that can be daunting to implement in an app. Thankfully, Framer Motion makes it a lot easier to implement its logic because of its declarative nature. In this post, I will give a simple, general introduction to it. However, in a future tutorial, I may explain with more details about how to create something more complex like a slide to delete.

Making an element draggable is extremely simple: add a `drag` prop to a `motion` component. Take for example the following:

```jsx
import { motion } from "framer-motion";

<motion.div drag>
  Hello World!
</motion.div>
```

Adding the `drag` prop will make it draggable in the x-axis and y-axis. It should be noted that you can restrict the movement to a single axis by providing the desired axis to `drag`.

There is a problem with just setting the `drag` property. It is not bound to any area or container so it can move outside the screen like this: 

![Card being dragged outside screen](https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599545000/getting-started-with-react-animations/7_vpjsem.gif)

To set constraints we give the `dragContraints` an object with our desired constraints for every direction: `top`, `left`, `right`,  and `bottom`. Take for example: 

```jsx
import { motion } from "framer-motion";

<motion.div
  drag
  dragConstraints={{
    top: -50,
    left: -50,
    right: 50,
    bottom: 50
  }}
>
  Hello World!
</motion.div>
```

These constraints allow the element to move 50 pixels maximum in any direction. If we try to drag it, for example, 51 pixels to the top, it will be stopped and bounced. Like this: 

![Card being dragged and colliding with constraints](https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599545092/getting-started-with-react-animations/ezgif.com-gif-maker_2_rurkh5.gif)

It is as there is an invisible wall with the form of a square that won't allow the component to move further.

> 📕 [Storybook Link](https://framer-animations.netlify.app/?path=/story/drag-block--main)

## Layout Property

The `layout` prop is a powerful feature in Framer Motion. It allows for components to animate automatically between layouts. It will detect changes to the style of an element and animate it. This has a myriad of use cases: reordering of lists, creating switches, and many more. 

Let's use this immediately! We'll build a switch. First, let's create our initial markup

```jsx
import { motion } from "framer-motion";

const Switch = () => {
  return (
    <div
      className={`flex w-24 p-1 bg-gray-400 bg-opacity-50 rounded-full cursor-pointer`}
      onClick={toggleSwitch}
    >
			{/* Switch knob */}
      <motion.div
        className="w-6 h-6 p-6 bg-white rounded-full shadow-md"
        layout       
      ></motion.div>
    </div>
  );
};
```

Now, let's add our logic:

```jsx
import { motion } from "framer-motion";

const Switch = () => {
	const [isOn, setIsOn] = React.useState(false);

  const toggleSwitch = () => setIsOn(!isOn);

  return (
    <div onClick={toggleSwitch}>
			{/* Switch knob */}
      <motion.div       
        layout       
      ></motion.div>
    </div>
  );
};
```

You may have noticed that only our knob has the `layout` prop. This prop is required on only the elements that we wish to be animated. 

We want the knob to move from one side to the other. We could achieve this by changing the container flex justification. When the switch is on then the layout will have `justify-content: flex-end`. Framer Motion will notice the knob's change of position and will animate its position accordingly.

Let's add this to our code: 

```jsx
import { motion } from "framer-motion";

const Switch = () => {
  const [isOn, setIsOn] = React.useState(false);

  const toggleSwitch = () => setIsOn(!isOn);

 return (
    <div
      style={{
	     background: isOn ? "#48bb78" : "rgba(203, 213, 224, 0.5)",
        justifyContent: isOn && "flex-end",
        width: "6rem",
        padding: "0.25rem",
        display: "flex",
        borderRadius: 9999,
        cursor: "pointer",   
      }}
      onClick={toggleSwitch}
    >
			{/* Switch knob */}
      <motion.div
        style={{
          width: "3rem",
          height: "3rem",
          background: "white",
          borderRadius: "100%",
          boxShadow:
            "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
        }}
        layout       
      ></motion.div>
    </div>
  );
};
```

I added some other styles so it can resemble the look of a switch. Anyway, here is the result: 

![Switch being toggled](https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599545162/getting-started-with-react-animations/11_eug7jn.gif)

Great! It is amazing how Framer Motion can do this automatically without having to deal with extra controls. Anyhow, it looks a little bland compared to what we are used to seeing on apps like Settings. We can fix this pretty quickly by adding a `transition` prop. 

```jsx
import { motion } from "framer-motion";

const Switch = () => {
 const [isOn, setIsOn] = React.useState(false);

 const toggleSwitch = () => setIsOn(!isOn);

 return (
    <div
      style={{
	     background: isOn ? "#48bb78" : "rgba(203, 213, 224, 0.5)",
        justifyContent: isOn && "flex-end",
        width: "6rem",
        padding: "0.25rem",
        display: "flex",
        borderRadius: 9999,
        cursor: "pointer",   
      }}
      onClick={toggleSwitch}
    >
			{/* Switch knob */}
      <motion.div
        style={{
          width: "3rem",
          height: "3rem",
          background: "white",
          borderRadius: "100%",
          boxShadow:
            "0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)",
        }}
        layout    
				transition={{
          type: "spring",
          stiffness: 500,
          damping: 30,
        }}   
      ></motion.div>
    </div>
  );
};
```

We define a spring-type animation because we want a bouncy feel. 

The `stiffness` defines how sudden the movement of the knob will look. 

And, `damping` defines the strength of the opposing force similar to friction. This means how fast it will stop moving. 

These together create the following effect: 

![Switch being toggled with spring effect.](https://res.cloudinary.com/dmq9pzw0o/image/upload/v1599545143/getting-started-with-react-animations/10_fus9tx.gif)

Now our switch looks more alive! 

> 📕 [Storybook Link](https://framer-animations.netlify.app/?path=/story/layout-switch--main)

## Conclusion

Creating animations can be daunting, especially when many libraries have complex jargon. Thankfully, Framer Motion allows developers to create seamless animations with its declarative an intuitive API. 

This post was meant as an introduction to the fundamentals of Framer Motion. In future posts, I will create complex animations like swipe to expand and delete, drawers, shared layout, and many more. Please let me know in the comments if you have any suggestions as to what you want to see animated!

For more up-to-date web development content, follow me on [Twitter](https://twitter.com/Jose_R_Felix), and [Dev.to](https://dev.to/jfelx)! Thanks for reading! 😎

- - -

Did you know I have a newsletter? 📬

If you want to get notified when I publish new blog posts and receive **awesome weekly resources** to stay ahead in web development, head over to <https://jfelix.info/newsletter>.