Framer Motion tutorial: How to easily create React animations
Tags: react, webdev
Published: 2023-07-13 17:16:32

**Written by [Paul Akinyemi](https://blog.logrocket.com/author/paulakinyemi/)✏️**

Animation in React, and on the web at large, is the process of changing the visual state of the UI elements on a page over time. What do I mean by visual state? Any property of the element that influences how it looks: height, shape, position relative to other elements, etc. The core idea of animation is that you’re changing some visible property of something on the page over time. 

There are a few ways to create animations in React, but all of them fall into two broad categories: CSS animations, which change visual state by applying CSS rules; and, JavaScript animations, which use JavaScript to change the properties of the element. In either of those categories, you can either implement the animation from scratch, or you can use a library. On the CSS side, you can compose your animations with CSS rules, or you can use third-party libraries like [Animate.css](https://animate.style/). 

If you choose to use JavaScript, you can either write custom code to create animations, or you can use libraries like GSAP or Framer Motion. Each library has its advantages, and each has a different approach for write animations. In this article, we’ll explore [Framer Motion](https://www.framer.com/motion/), a React animation library created and maintained by the Framer design team. 

You’ll learn the core components that underpin all Framer Motion animations, dive into some of the features that make Framer Motion a great tool, discover best practices to get the most out of the library, and put it all into practice with a step-by-step example. 

_Jump ahead_:

*   [Why Framer Motion for React animations?](#why-framer-motion-react-animations)
*   [Framer Motion components and APIs](#framer-motion-components-apis)
*   [Implementing animations in a React app using Framer Motion](#implementing-animations-react-app-using-framer-motion)
*   [Variants in Framer Motion](#variants-framer-motion)
*   [Framer Motion page transitions](#framer-motion-page-transitions)
*   [Building a drag-and-drop UI with Framer Motion](#building-drag-drop-ui-framer-motion)
*   [Integrating SVG animations](#integrating-svg-animations)
*   [Best practices for optimizing Framer Motion](#best-practices-optimizing-framer-motion)

To follow along, you’ll need:

*   Working knowledge of React, vanilla HTML, CSS, and JS
*   Working knowledge of the command line and npm

## Why Framer Motion for React animations? <a name="why-framer-motion-react-animations">

Why should you consider using Framer Motion in your React project? Framer Motion is a fairly popular and actively maintained library, with 19k stars on [Git](https://github.com/framer/motion)[H](https://github.com/framer/motion)[ub](https://github.com/framer/motion), and plenty of resources to support it. 

But most importantly, Framer Motion is built around the idea of allowing you to write complex, production-grade animations with as little code as possible. Using Framer Motion is so convenient that you can implement drag-and-drop by adding a single line of code! Framer Motion also greatly simplifies tasks like SVG animation and animating layout shifts.

## Framer Motion components and APIs <a name="framer-motion-components-apis">

Framer Motion has an intuitive approach to animation. It provides a set of components that wrap your markup and accept props to allow you to specify what type of animation you want. The core components of Framer Motion are:

*   The `motion` component
*   The `AnimatePresence` component

The `motion` component provides the foundation of all animation. It wraps the HTML elements in your React components and animates those elements with state passed to its `initial` and `animate` props. Below is an example. Take a plain div you might find anywhere on the web:

```javascript
<div>I have some content here</div>
```

Let’s assume you wanted this div to fade into the page when it loads. This code is all you need:

```javascript
<motion.div
  initial={{ opacity:0 }}
  animate={{ opacity:1 }}
>
  I have some content in here 
</motion.div>
```

When the page loads, the div will animate smoothly from transparency to full opacity, gradually fading into the page. In general, when the motion component is mounted, the values specified in the `initial` prop are applied to the component, and then the component is animated until it reaches the values specified in the `animate` prop. 

Next, let’s look at `AnimatePresence`. This component works with `motion` and is necessary to allow elements you remove from the DOM to show exit animations before they’re removed from the page. `AnimatePresence` only works on its direct children that fulfill one of two conditions:

*   The child is wrapped with a `motion` component
*   The child has an element wrapped with a `motion` component as one of its children

The exit animation you want has to be specified by adding the `exit` prop to `motion`. Here’s an example of `AnimatePresence` at work:

```javascript
<AnimatePresence>
  <motion.div
    exit={{ x: "-100vh", opacity: 0 }}
  >
    Watch me go woosh!
  </motion.div>
</AnimatePresence>
```

When the div wrapped by `AnimatePresence` is removed from the DOM, instead of just disappearing, it will slide 100vh to the left, fading into transparency as it does so. Only after that will the div be removed from the page. Note that when multiple components are direct children of `AnimatePresence`, they each need to have a `key` prop with a unique value so `AnimatePresence` can keep track of them in the DOM. 

Those two components are all you need for many animations, but Framer Motion has features that allow for more complex uses. One of those features is a set of props to a `motion` component that allows the component to trigger animations in response to gestures made by the end user, like hovering, tapping, or dragging page elements. These props are referred to as gestures. Here's a quick example that shows the use of the hover gesture:

```javascript
<motion.div
  whileHover={{
    opacity: 0
  }}
>
  Hover over me and I'll disappear!
</motion.div>
```

The `whileHover` prop is the hover gesture. The code above will fade out the div while it’s being hovered over, and return it to its previous state when the mouse leaves it. 

Let’s look at one last feature before we try a bigger example. What do you use if you want to tweak aspects of the animation, like adjusting the duration or delay? Framer Motion provides a `transition` prop that allows you to specify those. Framer Motion also allows you to choose between different types of animation, like [spring animations](https://www.joshwcomeau.com/animation/a-friendly-introduction-to-spring-physics) and tween (easing-based) animations, and the `transition` prop allows you to control that. Here’s an example:

```javascript
<motion.div
  initial={{ opacity:0 }}
  animate={{ opacity:1 }}
  transition={{ duration: 0.5, delay: 0.1 }}
>
  I have some content here 
</motion.div>
```

This is the same fade-in animation from earlier, but because of the `transition` prop, the animation will wait 0.1 seconds to start and will last for 0.5 seconds.

## Implementing animations in a React app using Framer Motion <a name="implementing-animations-react-app-using-framer-motion">

Let’s use everything we’ve learned to put together a more complex example. At the end of this article, you’ll have built an animated notification tray that looks like this: ![The Animated Notification Tray We Built In Framer Motion](http://blog.logrocket.com/wp-content/uploads/2023/06/animated-notification-tray-framer-motion.gif)

### Project setup and starter code

Start by navigating to the directory where you want the example to live. Next, open your terminal and create a starter React app using Vite with this command:

```javascript
npm create vite@latest
```

Then, answer the prompts like this: ![React Project Setup With Vite](http://blog.logrocket.com/wp-content/uploads/2023/06/react-project-setup-vite.png) Now, `cd` into the project you just created, run `npm install`, and then run `npm run dev`. Your project folder should now look like this: ![Framer Project Folder](http://blog.logrocket.com/wp-content/uploads/2023/06/framer-project-folder.png) Delete the `src/assets` folder and `App.css`. Now, write the code for the navigation tray without any animation. Start with the project’s CSS by replacing the contents of `index.css` with the following:

```css
:root {
  font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
  font-weight: 400;
}
body {
  margin: 0;
  min-width: 320px;
  min-height: 100vh;
  background-color: #fff;
  color: #111827;
}
header {
  height: 4rem;
  font-size: 1.1rem;
  border-bottom: 1px solid #e5e7eb;
  display: flex;
  align-items: center;
  padding: 0 2rem;
}
header > .header__left {
  width: 50%;
  font-size: 1.5rem;
}
header > .header__right {
  width: 50%;
  display: flex;
  justify-content: flex-end;
  align-items: center;
  list-style-type: none;
  margin: 0;
  padding: 0;
}
.header__right > * {
  margin: 0 1.5rem;
  position: relative;
}
.header__right > .notification__button {
  height: 2rem;
  width: 2rem;
  cursor: pointer;
}
.header__right > .notification__icon {
  height: 100%;
  width: 100%;
}
.header__right > .image {
  border-radius: 50%;
  height: 3rem;
  width: 3rem;
  overflow: hidden;
}
.header__right > .image > img {
  height: 100%;
  width: 100%;
}
.notification__tray {
  border-radius: 6px;
  box-shadow: 0px 0px 8px #e5e7eb;
  position: fixed;
  width: 24rem;
  top: 4.5rem;
  right: 2rem;
  color: rgb(65, 65, 81);
  font-size: 0.875rem;
  line-height: 1.25rem;
}
.notification__tray > ul {
  list-style-type: none;
  margin: 0;
  padding: 0;
}
.notification__tray li {
  padding: 1rem 2rem;
  border-bottom: 1px solid #e5e7eb;
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.notification__tray li:hover {
  background-color: #e5e7eb;
  color: #111827;
}
.notification__tray li .clear__button {
  width: 1.5rem;
  height: 1.5rem;
  cursor: pointer;
}
.notification__tray li .clear__icon {
  width: 100%;
  height: 100%;
}
.todo__header {
  text-align: center;
}
.todo__container {
  list-style-type: none;
}
.todo__item {
  border: 1px solid #e5e7eb;
  border-radius: 5px;
  box-shadow: 0px 0px 8px #e5e7eb;
  color: #111827;
  margin: 1.5rem auto;
  width: 350px;
  padding: 1.5rem 2rem;
  background-color: #e5e7eb;
}
```

Next comes the code for the page header. In `src`, create a file called `Header.jsx`, and fill it with this:

```javascript
import { useState } from "react";
import NotificationTray from "./NotificationTray";

const initialNotifications = [
  "User #20 left you a like!",
  "User #45 sent you a friend request",
  "Your song has been uploaded!",
  "Thanks for signing up!",
];

const Header = () => {
  const [showNotifications, setShowNotifications] = useState(false);
  const [notificationContent, setNotificationContent] =
    useState(initialNotifications);

  const handleDeleteNotification = (content) => {
    setNotificationContent(
      notificationContent.filter((item) => item !== content)
    );
  };

  return (
    <header>
      <div className="header__left">Brand</div>
      <ul className="header__right">
        <li
          className="notification__button"
          onClick={() => {
            setShowNotifications(!showNotifications);
          }}
        >
          <svg
            xmlns="http://www.w3.org/2000/svg"
            fill="none"
            viewBox="0 0 24 24"
            strokeWidth="1.5"
            stroke="currentColor"
            className="notification__icon"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5"
            />
          </svg>
        </li>
        <li className="image">
          <img src="https://www.dummyimage.com/48x48" />
        </li>
      </ul>

      {showNotifications ? (
        <NotificationTray
          notificationContent={notificationContent}
          handleDeleteNotification={handleDeleteNotification}
        ></NotificationTray>
      ) : null}
    </header>
  );
};
export default Header;
```

For brevity, we won’t go over the starter code in detail, but essentially it does a few things:

*   Imports the component for the notification tray
*   Creates state for the tray and defines a helper function to remove notifications from the state
*   Creates the markup for the header, and conditionally renders the tray

Next, write the code for the notification tray component. Create a file called `NotificationTray.jsx` and put this code in it:

```javascript
const NotificationTray = ({
  notificationContent,
  handleDeleteNotification,
}) => {
  return (
    <div className="notification__tray">
      <ul>
        {notificationContent.map((content) => {
          return (
            <li key={content}>
              <span>{content}</span>
              <span
                className="clear__button"
                onClick={() => {
                  handleDeleteNotification(content);
                }}
              >
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  fill="none"
                  viewBox="0 0 24 24"
                  strokeWidth={1.5}
                  stroke="currentColor"
                  className="clear__icon"
                  title="Clear notification"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    d="M9.75 9.75l4.5 4.5m0-4.5l-4.5 4.5M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
                  />
                </svg>
              </span>
            </li>
          );
        })}
      </ul>
    </div>
  );
};
export default NotificationTray;
```

This code:

*   Renders the state of the tray as a `<ul>`, with `<li>`s for each notification
*   Uses the helper function from `Header.jsx` to remove a notification when its clear button is clicked

Finally, render the header in `App.jsx` like this:

```javascript
import Header from "./Header"

function App() {
  return (
    <>
      <Header></Header>
    </>
  )
}
export default App
```

All of that covers the code necessary to get the notification tray working properly. If you look at your React app in the browser, you should have a webpage that looks like this: ![Webpage With Working Notification Tray](http://blog.logrocket.com/wp-content/uploads/2023/06/webpage-notification-tray.gif)

### Adding animation with Framer Motion

We’ll start animating a bell icon. The ringing motion that triggers on hover is created by rotating the SVG icon along the z-axis, in one direction and then the other, and then returning it to normal. 

Here’s how: at the top of `Header.jsx`, import `motion` and `AnimatePresence` from Framer Motion:

```javascript
import {motion, AnimatePresence} from "framer-motion";
```

Then, add animation to the SVG in `Header.jsx`:

```javascript
<motion.svg
  whileHover={{
    rotateZ: [0, -20, 20, -20, 20, -20, 20, 0],
    transition: { duration: 0.5 },
  }}
  xmlns="http://www.w3.org/2000/svg"
  fill="none"
  viewBox="0 0 24 24"
  strokeWidth="1.5"
  stroke="currentColor"
  className="notification__icon"
>
  <path
    strokeLinecap="round"
    strokeLinejoin="round"
    d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5"
  />
</motion.svg>
```

Here’s how the SVG changed:

*   It’s wrapped with `motion`
*   It has the `whileHover` gesture as a prop, so the animation only triggers when the SVG is hovered over
*   Inside the object passed to `whileHover`, you specified a range of values in an array. This array is called a keyframe, and it means that instead of animating to a single value, Framer Motion will animate the SVG to each of the values specified in the keyframe
*   Inside the object you passed to `transition`, you specified that you want the animation to last half a second

After applying that, you should see the bell ring when you hover over it on your webpage: ![Animated Bell Icon](http://blog.logrocket.com/wp-content/uploads/2023/06/animated-bell-icon.gif) The next animation you’ll implement is the fade-in on entry animation on the notification tray. Enter `Notification.jsx` and import `motion` and `AnimatePresence`:

```javascript
import { motion, AnimatePresence } from "framer-motion";
```

Then, modify the outermost `div` like so:

```javascript
<motion.div
  className="notification__tray"
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
>
  <ul>
    .....
  </ul>
</motion.div>
```

All that changed is that the `div` became `motion.div`, and you set the values of the `initial` and `animate` props so the div starts with an `opacity` of 0 and animates to become fully visible. Repeat this on the `<li>`s returned from the `map` and add a duration of 0.2 seconds like so:

```javascript
{
  notificationContent.map((content) => {
    return (
      <motion.li
        key={content}
        initial={{ opacity: 0 }}
        animate={{ opacity: 1 }}
        transition={{ duration: 0.2 }}
      >
        ...
      </motion.li>
    )
  })
}
```

As an extra touch, let’s animate the exit of each notification. You’ll do this by adding a slide-away animation when an `li` is removed from the tray. All you need to do now is wrap the `<li>`s with an `AnimatePresence` component, and then use the `exit` prop to specify what should happen when each `<li>` is removed. Let’s see how that works:

```javascript
<ul>
  <AnimatePresence>
    {notificationContent.map((content) => {
      return (
        <motion.li
          key={content}
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ x: "-12rem", opacity: 0 }}
          transition={{ duration: 0.2 }}
          layout
        >
          ....
        </motion.li>
      )
    })}
  </AnimatePresence>
</ul>
```

The `exit` prop says that when the `<li>` is removed, it should move 12rem (half the width of the tray) to the left, and then fade away before being unmounted. The `layout` prop tells Framer Motion to animate any changes in the element’s position caused by layout shifts. This means that when an `<li>` is removed from the tray, instead of its siblings jumping up to fill the space, they’ll smoothly glide into their new positions instead. Take a minute to check it out for yourself. 

Your last task for this section is to animate the exit of the tray (when it disappears after you click the bell). The animation you want to apply is the same as the exit animation on the `<li>`s: slide left and fade away. 

Go back into `Header.jsx` and wrap the `NotificationTray` component with `AnimatePresence`:

```javascript
<AnimatePresence>
  {showNotifications ? (
    <NotificationTray
      notificationContent={notificationContent}
      handleDeleteNotification={handleDeleteNotification}
    ></NotificationTray>
  ) : null}
</AnimatePresence>
```

Then, inside `NotificationTray.jsx`, add an exit prop to the outermost div:

```javascript
<motion.div
  className="notification__tray"
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  exit={{ opacity: 0, x: "-12rem" }}
>
  <ul>...</ul>
</motion.div>
```

And that completes the basics of our animations! Your tray should now have animations that look like this: ![Working Animations In Our Notification Tray Using Framer Motion](http://blog.logrocket.com/wp-content/uploads/2023/06/working-animations-notification-tray-framer-motion.gif) Next, you’ll see how to use variants to clean up your code and orchestrate child animations.

## Variants in Framer Motion <a name="variants-framer-motion">

Variants are a mechanism Framer gives you that serve two purposes:

*   They make your code cleaner by allowing you to reduce repetition
*   They allow you to coordinate the animations of children with the animations of their parents, which means you can do things like stagger child animations

So, what exactly do variants look like? They’re just objects that hold the objects you would pass to the props to a `motion` component. It’s easier to understand when you see them, so here’s an example:

```javascript
const dummyVariant = {
  initial: { opacity: 0 },
  animate: { opacity: 1 },
}
```

The `dummyVariant` object holds the objects you’d have passed to the `initial` and `animate` props. The property names don’t have to match the name of the prop they’ll be assigned to, so the variant would have worked the same if it was simply:

```javascript
const dummyVariant = {
  hide: { opacity: 0 },
  show: { opacity: 1 },
}
```

To use a variant on a `motion` component, you have to pass the variant to the `variants` prop of your motion component. Then you can pass the props of the `motion` component the property names of the objects inside of your variant instead of having to type out the full object. Here’s an example:

```javascript
><motion.div variants={dummyVariant} initial="hide" animate="show">
  Watch me!
</motion.div>
```

Now that you have a general idea of how variants work, let’s go back and use variants to improve our notification tray. Open `NotificationTray.jsx` and add this code just under the import:

```javascript
const notificationVariants = {
  initial: { opacity: 0 },
  animate: { opacity: 1, transition: { staggerChildren: 0.15 } },
  exit: {
    x: "-12rem",
    opacity: 0,
    transition: {
      staggerChildren: 0.15,
      staggerDirection: -1,
      when: "afterChildren",
    },
  },
}
```

This code introduced a few new properties, so let’s examine them. Variants allow you to adjust the timing of animations on child elements relative to the animation on their parents with special `transition` props like `staggerChildren`. The `staggerChildren` prop allows you to delay the animation of each child by a constant difference. 

For instance, if `staggerChildren` is set to `0.15`, the first child will be delayed by `0` seconds, the second by `0.15`, the third by `0.30`, and so on. `staggerDirection` can either be `1` or `-1` and allows you to decide whether the stagger should start from the first child or the last one. The `when` prop applies to the parent. It defines whether the parent’s animation should start before the children start animating or only start after all the children are done. 

In the variant you just defined, you staggered the input and exit animation of each child by 0.15 seconds, and said the stagger on the exit animations should start from the last child. You also said the parent’s exit animation should only start after the exit animations of all its children have ended. 

Now that you have a variant defined, the outermost div can be refactored to this:

```javascript
<motion.div
  className="notification__tray"
  variants={notificationVariants}
  initial="initial"
  animate="animate"
  exit="exit"
>
  <ul>...</ul>
</motion.div>
```

And the `<li>`s can be refactored to this:

```javascript
<motion.li
  key={content}
  variants={notificationVariants}
  exit={{ x: "-12rem", opacity: 0 }}
  transition={{ exit: { duration: 0.1 } }}
  layout
>
  ...
</motion.li>
```

You might notice that the `initial` and `animate` props are no longer on the `<li>`, but the animation still works. This is due to another feature of variants called propagation. Propagation means when a `motion` component and its children are using variants, the values of the `initial` and `animate` props will flow down from the parent to the children until one of the children defines its own `animate` prop. 

After putting it all together, your webpage should now look like this: ![Using Variants In Framer Motion Animations](http://blog.logrocket.com/wp-content/uploads/2023/06/variants-framer-motion-animation.gif) And that’s it! You can find the complete code for this example in the [Framer Motion documentation](https://www.framer.com/motion/animate-presence/).

## Framer Motion page transitions

Framer Motion can also integrate with React Router 6, allowing you to animate routing transitions with `AnimatePresence` as pages in your app are mounted and unmounted. Here's an [example CodeSandbox](https://codesandbox.io/s/framer-motion-react-router-6-page-transitions-2f2olf?from-embed) from the official docs.

## Building a drag-and-drop UI with Framer Motion <a name="building-drag-drop-ui-framer-motion">

Just like everything else, Framer Motion makes implementing drag-and-drop easy. To make an element draggable, first wrap it with a motion component, and then add the drag prop. That’s all you need. As an example, you go from this:

```javascript
<div>Drag me around!</div>
```

To this:

```javascript
<motion.div drag>Drag me around</motion.div>
```

And that’s it! Doing that will let you drag the div anywhere, including off the screen. That's why Framer Motion provides extra props like `dragConstraint` to let you limit the range a component can be dragged to, and `dragElastic` moderates how elastic the boundary is. 

`dragConstraint` accepts either an object with values for top, left, right, and bottom, or a ref to another DOM object. The value of `dragElastic` ranges from `0`, meaning the boundaries aren’t elastic at all, to `1`, where the boundaries are as elastic as possible. Here’s an example:

```javascript
 <motion.div
  drag
  dragConstraints={{
    top: -50,
    left: -50,
    right: 50,
    bottom: 50,
  }}
  dragElastic={0.3}
>
  Drag me around
</motion.div>
```

Now, the `div` can only be dragged in a region 50px in any direction, and the boundaries of the region are slightly elastic.

## Integrating SVG animations

Framer also makes animating SVGs a breeze, by allowing you to animate the `pathLength`, `pathSpacing`, and `pathOffset` properties of those SVGs. Here’s an example that uses the same bell icon we used in our header bar. Animate the `pathLength` of the SVG in `Header.js` by updating it like this:

```javascript
<motion.svg
  initial={{ pathLength: 0 }}
  animate={{ pathLength: 1 }}
  whileHover={{
    rotateZ: [0, -20, 20, -20, 20, -20, 20, 0],
    transition: { duration: 0.5 },
  }}
  xmlns="http://www.w3.org/2000/svg"
  fill="none"
  viewBox="0 0 24 24"
  strokeWidth="1.5"
  stroke="currentColor"
  className="notification__icon"
>
  <motion.path
    initial={{ pathLength: 0 }}
    animate={{ pathLength: 1 }}
    transition={{ duration: 2 }}
    strokeLinecap="round"
    strokeLinejoin="round"
    d="M14.857 17.082a23.848 23.848 0 005.454-1.31A8.967 8.967 0 0118 9.75v-.7V9A6 6 0 006 9v.75a8.967 8.967 0 01-2.312 6.022c1.733.64 3.56 1.085 5.455 1.31m5.714 0a24.255 24.255 0 01-5.714 0m5.714 0a3 3 0 11-5.714 0M3.124 7.5A8.969 8.969 0 015.292 3m13.416 0a8.969 8.969 0 012.168 4.5"
  />
</motion.svg>
```

On page load, the SVG should animate like this: ![](https://paper-attachments.dropboxusercontent.com/s_8B7F1A4824A0710A7A3E2BD0EEC859F800EAC1D61F1044F0E21BBDF9E1F362D7_1687029597037_bell-animation-cropped.gif)

## Best practices for optimizing Framer Motion <a name="best-practices-optimizing-framer-motion">

Framer Motion is a great tool, but like any tool, it can be misused. Here are a few rules of thumb to optimize performance when using Framer Motion:

*   Use the [`layoutGroup`](https://www.framer.com/motion/layout-group/) component and `layoutId` prop for shared element animations
*   Leverage hardware acceleration by animating `transform` and `opacity` properties whenever possible
*   Where possible, wrap multiple elements within a parent component and animate the parent to reduce the number of animations
*   If you have animations that trigger frequently (e.g., on scroll or mouse movement), consider using debounce or throttle techniques to limit the number of animation updates and improve performance
*   Use Framer Motion’s hooks instead of rewriting the functionality yourself

Following these practices will help you optimize performance and create smoother animations with Framer Motion in React.

## Conclusion

Web animation is the process of changing the visual state of UI elements over time. Web animation utilizes one of two approaches: CSS or JavaScript. Framer Motion is a popular, well-supported JavaScript-based animation library for React applications that simplifies the process of implementing complex animations. In this article, we used Framer Motion to build an animated notification tray, animate an SVG, and implement drag-and-drop. 

I hope you enjoyed this article. Happy coding!

---

##Get setup with LogRocket's modern React error tracking in minutes:

1.Visit https://logrocket.com/signup/ to get an app ID.
2.Install LogRocket via NPM or script tag. `LogRocket.init()` must be called client-side, not server-side.

NPM:
```bash
$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
```
Script Tag:
```javascript
Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
```

3.(Optional) Install plugins for deeper integrations with your stack:
*   Redux middleware
*   ngrx middleware
*   Vuex plugin

[Get started now](https://lp.logrocket.com/blg/signup)