How to Add Animations to Your React Apps With Framer Motion
Learn how to add simple animations to your React app with a minimum of coding effort.
Animation is a crucial part of almost every modern web application. It is also one of the most difficult parts to get right.
Framer Motion is a library built for React that makes it easy to animate components.
Framer Motion uses the motion component for animations. Each HTML/SVG element has an equivalent motion component that has props for gestures and animations. For example, a regular HTML div looks like this:
While the Framer Motion equivalent looks like this:
Motion components support an animate prop that triggers animations when its values change. For complex animations, use the useAnimate hook with a scoped ref.
Before using Framer Motion in your project, you need to have the Node.js runtime and the Yarn package manager installed on your computer and understand what React is and how to use it.
You can view and download this project's source code from its GitHub Repository. Use the starter-files branch as a starter template to follow along with this tutorial, or the final-files branch for the complete demo. You can also see the project in action via this live demo.
Open your terminal and run:
When you open localhost:5173 in your browser, you will see this:
You can now create your first simple animation, a button that grows on hover and shrinks when the cursor leaves.
Open the src/App.jsx file in a code editor. This file contains a functional component that returns a React fragment. Import the Button component, then render it, passing in a text prop:
Next, edit the Button.jsx file and import the motion utility from framer-motion:
Now, replace the regular button element with the motion.[element] component. In this case, use the motion.button component.
Then add a whileHover gesture prop and pass an object of values that Framer Motion should animate to when a user hovers over the button.
The button will now animate when you move your mouse pointer over it or out of it:
You might be wondering why this demo doesn't use CSS Animations instead. Framer Motion has advantages over CSS because it integrates with React state and generally results in cleaner code.
Next, try something more complex: animating a modal. In Backdrop.jsx, import the motion utility and create a functional component with onClick and children props. Return a motion.div component with class "backdrop" and onClick listener in the JSX.
Then add three props namely: initial, animate, and exit. These props represent the original state of the component, the state the component should animate to, and the state the component should be in after animation, respectively.
Add onClick and children props to the motion.div and set the transition duration to 0.34 seconds:
The Backdrop component is a wrapper for the Modal component. Clicking the backdrop dismisses the modal. In Modal.jsx, import motion and the Backdrop component. The default functional component accepts props: closeModal and text. Create a variant variable as an object.
Return a motion.div component wrapped by a Backdrop component with a "variants" prop pointing to the variants object. Variants are a set of predefined animation states that the component could be in.
Next, you need to add the functionality to display the modal when a user clicks the button. Open the App.jsx file and import the useState React hook and the Modal component.
Then create a modalOpen state with the default value set to false.
Next, define a function closeModal that sets the modalOpen to false.
At the top of the React fragment, conditionally render a Modal component and pass the appropriate text prop with the closeModal prop.
Then, in the second section element, render a button element with an onClick event handler that sets modalOpen to false.
You might notice that React unmounts the Modal component from the DOM without an exit animation. To fix that, you need an AnimatePresence component. Import AnimatePresence from framer-motion.
Now, wrap the Modal component in the AnimatePresence component and set the initial prop to false and the mode to "wait".
The AnimatePresence component allows exit animations to complete before React unmounts it from the DOM.
Framer Motion can animate components on scroll using the whileInView prop. Open the ScrollElement.jsx, and import the motion utility. Change div to motion.div with class "scroll-element".
The viewport prop points to an object that sets once to true. Next, in the App.jsx file, import the ScrollElement component and define a variable scrollElementCount that holds an integer value.
In the last section element, create an array with a specific length defined by scrollElementCount that maps over each element of the array and generates a component with a unique key based on the index i.
Now, returning to the browser, elements should animate when you scroll them into view.
Framer Motion is not the only animation library on the market. If you do not like the way Framer Motion does things, you can try out other libraries like React Spring.
You can also use CSS animations, which all modern browser support natively, but the techniques involved can be tricky to learn and set up.
Every user expects a buttery smooth experience when using a web application. A website or application without animations feels static and unresponsive. Animations improve the user experience because you can use them to communicate feedback to the user when they perform a certain action.
David Uzondu is a JavaScript Developer with 3+ years of experience. He loves writing in his spare time.
MAKEUSEOF VIDEO OF THE DAY SCROLL TO CONTINUE WITH CONTENT animate useAnimate starter-files final-files localhost:5173 src/App.jsx Button text Button.jsx motion framer-motion button motion.[element] motion.button whileHover Backdrop.jsx onClick children motion.div onClick initial animate, exit onClick children motion.div Backdrop Modal Modal.jsx motion closeModal text App.jsx useState Modal modalOpen false closeModal modalOpen Modal text section button AnimatePresence framer-motion initial mode whileInView ScrollElement.jsx motion div motion.div viewport once true App.jsx ScrollElement section scrollElementCount i