5 Cool Animations in React with Framer Motion

Oct 25, 20235 MIN READ
5 Cool Animations in React with Framer Motion

Animations are a powerful tool to enhance user experience, and when it comes to creating animations in React, Framer Motion is a popular library of choice. In this blog post, we'll explore 5 cool animations you can create in React using Framer Motion.

You can also learn more complex animations with Framer Motion in this article!.


Framer Motion is a versatile animation library for React, known for its simplicity and powerful animations. If you're looking for an alternative, you can explore React Spring, which I've covered in my article here.

Now, let's dive into five cool animations you can create in React using Framer Motion!

1. Button Tap Animation

This is a really simple yet fun effect to add to your buttons. It adds a fun touch to your buttons by scaling them when tapped. To add this, we can make use of the whileTap property. We can scale the button up or down within this property:

import { motion } from "framer-motion"; function App() { return ( <motion.button whileTap={{ scale: 0.85 }} > Click me! </motion.button> ); } export default App;

The result will look somewhat like this:

Prerendered

2. Text Typing Animation

Text typing animations, created with Framer Motion, add a playful touch to engage users, useful for loading messages and chat simulations. To achieve this effect, we will take a sentence we want to display and convert it into an array of words. Next, we will map this array out and add an animation and transition on the opacity, as well as a delay that creates the typing effect.

import "./styles.css"; import { motion } from "framer-motion"; function App() { const text = "Framer Motion is a really cool tool".split(" "); return ( <div className="App"> {text.map((el, i) => ( <motion.span initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 0.25, delay: i / 10 }} key={i} > {el}{" "} </motion.span> ))} </div> ); } export default App;
Prerendered

3. Stagger Animations

Stagger animations, as demonstrated in dropdowns and navigation menus, involve animating elements in a sequential manner, each appearing one after the other, with a subtle delay distinguishing their appearances. You can create much more complex effects using this method as opposed to the ones mentioned above.

In this example, we will animate in some menu items when a menu button is clicked. We will use the stagger function alongside motion and useAnimate. Learn more about useAnimate here.

import { useAnimate, stagger, motion } from "framer-motion";

Start by creating an array that holds the list of items to be displayed in the menu. To achieve this effect, the list items are initially mapped within a <ul> element. When the button is clicked, the <ul> is first made visible. Then, the list items will animate in a staggered fashion one by one.

We will utilize the useAnimate hook to generate the animations for both the <ul> and <li> elements. These animations will be triggered by a change in state, which can be toggled using the button.

import "./styles.css"; import { useState, useEffect } from "react"; import { useAnimate, stagger, motion } from "framer-motion"; export default function App() { const [open, setOpen] = useState(false); const [scope, animate] = useAnimate(); const items = ["Item 1", "Item 2", "Item 3", "Item 4"]; // the stagger effect const staggerList = stagger(0.1, { startDelay: 0.25 }); // create the animations that will be applied // whenever the open state is toggled useEffect(() => { animate( "ul", { width: open ? 150 : 0, height: open ? 200 : 0, opacity: open ? 1 : 0 }, { type: "spring", bounce: 0, duration: 0.4 } ); animate( "li", open ? { opacity: 1, scale: 1, x: 0 } : { opacity: 0, scale: 0.3, x: -50 }, { duration: 0.2, delay: open ? staggerList : 0 } ); }, [open]); return ( <div className="App" ref={scope}> <motion.button onClick={() => setOpen(!open)} whileTap={{ scale: 0.95 }}> Menu </motion.button> <ul> {items.map((item, index) => ( <motion.li key={index}>{item}</motion.li> ))} </ul> </div> ); }
Prerendered

4. Count Animation

This effect is commonly used for displaying numbers and statistics and is often used in countdown timers.

To implement this effect, we'll utilize MotionValues to monitor the state and velocity of the values, and we'll employ the animate function to specify the animation duration.

import { motion, useMotionValue, animate } from "framer-motion";

We will pass it an initial state or value which will be 0. Then we will count up to 50. Keep in mind that you need to round the count to make sure no decimal points are shown. For this, useTransform will be used.

import "./styles.css"; import { motion, useMotionValue, useTransform, animate } from "framer-motion"; import { useEffect } from "react"; export default function App() { const count = useMotionValue(0); const rounded = useTransform(count, Math.round); useEffect(() => { const animation = animate(count, 50, { duration: 2 }); return animation.stop; }, []); return <motion.h1>{rounded}</motion.h1>; }

In the code above, animation.stop is being used to stop the animation when the component is unmounted. This ensures that the animation is terminated, and any resources associated with the animation are released.

Prerendered

5. Scroll Reveal Animations

Scroll reveal animations are a great way to make websites engaging and appealing to users. For instance, you can create effects like fading an element in or smoothly sliding it into view as it becomes visible on the screen. To create this effect, we can use the whileInView and viewport props. Here's an example of how to use these props to achieve a scroll reveal effect:

<motion.div initial="hidden" whileInView="visible" viewport={{ once: true }} />

We can add animations and effects within the initial and whileInView props. Variants can also be used for this purpose. In the example below, we are going to slide in some elements when they come into view:

import React from "react"; import { motion } from "framer-motion"; function Card({ text, index }) { return ( <motion.div className="card" initial={{ opacity: 0, // if odd index card,slide from right instead of left x: index % 2 === 0 ? 50 : -50 }} whileInView={{ opacity: 1, x: 0, // Slide in to its original position transition: { duration: 1 // Animation duration } }} viewport={{ once: true }} > <p className="card-text">{text}</p> </motion.div> ); } export default Card;

You can set viewport={{ once: true }} to false if you want the effect to occur every time the element is scrolled into or out of view.

Prerendered

Thanks for reading!