React scroll animations with Framer Motion

Written by David Omotayo✏️

Animations can present a robust person expertise if they’re effectively executed. Nonetheless, making an attempt to create beautiful animations with CSS will be nerve-wracking. Many animation libraries promise to simplify the method, however most easily aren’t complete sufficient for constructing complicated animations.

On this article, we’ll show learn how to create scroll animations with Framer Motion, an entire animation library that does not require you to be a CSS professional to create lovely animations.

Soar forward:



Conditions

  • Working information of React and its ideas, together with Hooks
  • Working information of CSS properties equivalent to opacity, transition, and scale

There’s no must have any prior information of Framer Movement. This text will introduce the library’s fundamental ideas and construct on these within the demonstration portion.

Let’s begin with slightly background on Framer Movement and intersection observer performance.



What’s Framer Movement?

Framer Movement is an animation library for creating declarative animations in React. It gives production-ready animations and a low-level API to assist simplify the method of integrating animations into an software.

Some React animations libraries, like react-transition-group and transition-hook, animate elements with manually configured CSS transitions. Framer Movement takes a special method, by animating components underneath the hood with preconfigured kinds.

movement and uaeAnimation are two kinds which can be triggered and managed by features uncovered by Framer Movement. The movement operate is used to create movement parts, and these are the constructing blocks of Framer Movement.

By prefixing movement to an everyday HTML or SVG ingredient, the ingredient mechanically turns into a movement part:

Movement Part

A movement part has entry to a number of props, together with the animate prop. animate takes in an object with the outlined properties of the parts to be animated. The properties outlined within the object are animated when the part mounts.



What’s intersection observer performance?

Framer Movement animates components once they mount on the DOM. It would not have inbuilt performance for animating components primarily based on their scroll place on the viewport. To deal with this, we’ll must implement an intersection observer performance that can stop a component from mounting till its scroll place is within the viewport.

We will construct this performance from scratch as a customized Hook utilizing the Intersection Observer API. This JavaScript API gives a strategy to asynchronously observe adjustments within the intersection of a goal ingredient with a top-level doc viewport.

In accordance with the documentation, this API registers a callback operate that’s executed each time a component we need to monitor enters or exits one other ingredient or enters or exits the viewport.

Alternatively, we will use a library that’s designed to deal with this performance. That is the method that we’ll observe on this article. We’ll be utilizing the react-intersection-observer library, which is a React implementation of the intersection observer API. This library gives Hooks and render props that make it straightforward to trace the scroll place of components on the viewport.

react-intersection-observer is a comparatively small bundle, so there’s no want to fret in regards to the overhead it might add to your challenge.

Supply: bundlephobia.

Now, let’s arrange a easy React challenge and set up the required dependencies.



Getting began

We’ll begin by putting in React:

npx create-react-app my-app
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we’ll set up Framer Movement and react-intersection-observer:

npm i react-intersection-observer framer-motion
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we’ll arrange a demo app and can use Framer Movement and the react-intersection-observer library to establish when the weather are in view after which apply an animation.



Creating the demo app

First, we’ll create a field part (this may very well be a or card, modal, or anything) and import it into the primary part, App.js . We’ll animate this principal part when it enters the viewport.

/*Field part*/
const Field = () => {
  return (
    <div className="field">
      <h1>Field</h1>
    </div>
  );
};

/*Important part*/
export default operate App() {
  return (
    <div className="App">
      <Field /> /*imported Field part*/ /*imported Field part*/
    </div>
  );
}
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we’ll import every thing else that’s required to create animation from the libraries we put in earlier:

  • movement and useAnimation Hooks from Framer Movement
  • useEffect Hook from React
  • useInView Hook from react-intersection-observer
import { movement, useAnimation } from "framer-motion";

    import { useInView } from "react-intersection-observer";

    import { useEffect } from "react";
Enter fullscreen mode

Exit fullscreen mode

These are the important Hooks we’ll must animate our field part. You’ll get an thought of how every Hook works slightly later on this tutorial.

Inside our part is a div ingredient with the className: field. As a way to animate the field ingredient, we have to make it a movement part.

We do that by prefixing movement to the ingredient:

const Field = () => {
  return (
    <movement.div className="field">
      <h1>Field</h1>
    </movement.div>
  );
};
Enter fullscreen mode

Exit fullscreen mode

We will begin animating the field ingredient as is, by merely including an preliminary and animate prop to the movement part and immediately defining their object values.

<movement.div 
animate={{ x: 100 }} 
preliminary={{x: 0}} 
className="field"
></movement.div>
Enter fullscreen mode

Exit fullscreen mode

For extra complicated animation, Framer Movement presents a variants characteristic.



Animating with variants

Variants are a set of predefined objects that allow us declaratively outline how we wish the animation to look. Variants have labels that may be referenced in a movement part to create animations.

Right here’s an instance of a variant object:

const exampleVariant = {
  seen: { opacity: 1 },
  hidden: { opacity: 0 },
}
Enter fullscreen mode

Exit fullscreen mode

Inside this variant object, exampleVariant, are two properties: seen and hidden. Each properties are handed an object as the worth. When the ingredient is seen, we wish the opacity to be 1; when it’s hidden, we wish it to be 0.

The above variant object will be referenced in a movement part, like so:

<movement.div variants={exampleVariant} />
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we’ll create a variant and cross it as a prop to our movement part:

const boxVariant = {
  seen: { opacity: 1, scale: 2 },
  hidden: { opacity: 0, scale: 0 },
}
Enter fullscreen mode

Exit fullscreen mode

On this variant object, boxVariant, we included a scale property in order that the ingredient will scale up in dimension when it’s seen and scale down when it’s hidden.

To reference this variant object it in our movement part, we’ll add a variants prop to the movement part and cross it the variant’s label:

<movement.div
  variants={boxVariant}
  className="field"
/>
Enter fullscreen mode

Exit fullscreen mode

Proper now, nothing is occurring to our movement part; it has entry to the variant object, but it surely would not know what to do with it. The movement part wants a strategy to know when to begin and finish the animations outlined within the variant object.

For this, we cross the preliminary and animate prop to the movement part:

<movement.div
  variants={boxVariant}
  className="field"
  preliminary="..."
  animate="..."
/>
Enter fullscreen mode

Exit fullscreen mode

Within the above code, the preliminary prop defines the habits of a movement part earlier than it mounts, whereas the animate prop is used to outline the habits when it mounts.

Now, we’ll add a fade-in animation impact to the movement part by setting the opacity of the part to 0 earlier than it mounts and again to 1 when it mounts. The transition property has a length worth that signifies the animation length.

<movement.div
  className="field"
  preliminary={{ opacity: 0, transition:{length: 1}}}
  animate={{opacity: 1}}
/>
Enter fullscreen mode

Exit fullscreen mode

Since we’re utilizing variants, we do not have to explicitly set the values of the preliminary and animate properties.

As a substitute, we will dynamically set them by referencing the hidden and seen properties within the variant object we created earlier:

const boxVariant = {
  seen: { opacity: 1, scale: 2 },
  hidden: { opacity: 0, scale: 0 },
}
...
<movement.div
  variants={boxVariant}
  preliminary="hidden"
  animate="seen"
  className="field"
/>
Enter fullscreen mode

Exit fullscreen mode

The movement part will inherit the values of the variant object’s hidden and seen properties and animate accordingly:

Two Boxes Animate at Once

Now that we’ve got a working animation for our movement part, the following step is to make use of the react-intersection-observer library to entry the Intersection Observer API and set off the animation when the part is in view.



Including scroll reveal animation with useInView and useAnimation Hooks

Framer Movement animates components once they mount, so earlier than we will animate components primarily based on their scroll place, we want to have the ability to management once they mount and unmount.

The useAnimation Hook gives helper strategies that allow us management the sequence by which our animations happen. For instance, we will use the management.begin and management.cease strategies to manually begin and cease our animations.

useInView is a react-intersection-observer Hook that lets us monitor when a part is seen within the viewport. This Hook offers us entry to a ref, that we will cross into the parts we need to watch, and the inView Boolean, which tells us whether or not a part is within the viewport.

For instance, if we cross ref to a part as a prop and log inView to the console, the console will show true when the part is scrolled into the viewport and false when it leaves the viewport.

False and True Outputs

Now, we’ll use the useAnimation Hook to set off animations on our movement part with when it enters the viewport.

First, we’ll destructure ref and inView from the useInView Hook, and assign useAnimation to a variable:

const management = useAnimation()
const [ref, inView] = useInView()
Enter fullscreen mode

Exit fullscreen mode

Subsequent, we’ll add ref to our movement part as a prop and cross the management variable as a worth to the animate prop:

<movement.div
  ref={ref}
  variants={boxVariant}
  preliminary="hidden"
  animate={management}
  className="field"
/>
Enter fullscreen mode

Exit fullscreen mode

Lastly, we’ll create a useEffect to name the management.begin methodology each time the part we’re watching is in view, and cross the management and inView variables because the dependencies:

useEffect(() => {
    if (inView) {
      management.begin("seen");
    } 
  }, [control, inView]);
Enter fullscreen mode

Exit fullscreen mode

Contained in the useEffect callback operate, we carry out a conditional test with an if assertion to test if the movement part is in view. If the situation is true, useEffect will name the management.begin methodology with a "seen" worth handed into it. It will set off the animate property on our movement part and begin the animation.

Now, if we scroll up and down our viewport, the field parts will animate when their scroll place enters the viewport:

Boxes Animate While Scrolling

Discover how the field parts solely animate the primary time they enter the viewport. We will make them animate each time they’re in view by including an else block to the if assertion within the useEffect callback operate, and calling the management.begin methodology, however with a "hidden" worth handed into it this time.

else {
      management.begin("hidden");
    }
Enter fullscreen mode

Exit fullscreen mode

Now, if we scroll up and down our viewport, the field parts will animate every time their scroll place enters the viewport:

Boxes Animate Into Viewport

Right here’s a take a look at the ultimate code for creating scroll animations with Framer Movement:

import { movement, useAnimation } from "framer-motion";
import { useInView } from "react-intersection-observer";
import { useEffect } from "react";

const boxVariant = {
  seen: { opacity: 1, scale: 1, transition: { length: 0.5 } },
  hidden: { opacity: 0, scale: 0 }
};

const Field = ({ num }) => {

  const management = useAnimation();
  const [ref, inView] = useInView();

  useEffect(() => {
    if (inView) {
      management.begin("seen");
    } else {
      management.begin("hidden");
    }
  }, [control, inView]);

  return (
    <movement.div
      className="field"
      ref={ref}
      variants={boxVariant}
      preliminary="hidden"
      animate={management}
    >
      <h1>Field {num} </h1>
    </movement.div>
  );
};

export default operate App() {
  return (
    <div className="App">
      <Field num={1} />
      <Field num={2} />
      <Field num={3} />
    </div>
  );
}
Enter fullscreen mode

Exit fullscreen mode



Conclusion

On this article, we launched the fundamentals of the Framer Movement animation library and demonstrated learn how to use it to create scroll animations. We mentioned learn how to management animations utilizing the useAnimation Hook, and learn how to set off animations with Intersection Observer API (accessed by way of the react-intersection-observer library).

This text presents only a glimpse into the intensive vary of animations that may be created with Framer Movement. Go to the official docs and see what else you’ll be able to provide you with.




Full visibility into manufacturing React apps

Debugging React purposes will be tough, particularly when customers expertise points which can be arduous to breed. If you happen to’re considering monitoring and monitoring Redux state, mechanically surfacing JavaScript errors, and monitoring gradual community requests and part load time, try LogRocket.

LogRocket signup

LogRocket is sort of a DVR for internet and cellular apps, recording actually every thing that occurs in your React app. As a substitute of guessing why issues occur, you’ll be able to combination and report on what state your software was in when a problem occurred. LogRocket additionally screens your app’s efficiency, reporting with metrics like consumer CPU load, consumer reminiscence utilization, and extra.

The LogRocket Redux middleware bundle provides an additional layer of visibility into your person classes. LogRocket logs all actions and state out of your Redux shops.

Modernize the way you debug your React apps — start monitoring for free.

Add a Comment

Your email address will not be published. Required fields are marked *