Scroll Trigger Animation In Framer Motion

Scroll Trigger Animation is a animation in which when we scroll to that section the animation will be triggered and it will be played instead of playing it on page load.

Note: Scroll Trigger and Scroll Based Animation are different. Scroll Based Animation is the animation which is played based on the scroll position but in Scroll Trigger Animation the animation is played when we scroll to that section.

Why We Need Scroll Trigger Animation?

Basically when we use animate prop the animation is played on page load but if we want to play the animation when we scroll to that section then we can use Scroll Trigger Animation.

whileInView prop

In Framer Motion we can achieve Scroll Trigger Animation using the whileInView prop. The whileInView prop takes an object of animation properties which will be applied when the element is in the viewport.Instead of using animation props like animate we use the whileInView prop to trigger the animation when the element is in the viewport which will animate when we scroll to that section.

import { motion } from "framer-motion";
export default function App() {
  return (
    <div style={{ height: "150vh", padding: "50px" }}>
      <motion.div
        style={{
          width: 100,
          height: 100,
          backgroundColor: "blue",
          margin: "0 auto",
        }}

        initial={{ scale: 1, rotate: 0 }}
        whileInView={{ scale: 1.5, rotate: 90 }}
        transition={{ duration: 0.5 }}
      />
    </div>
  );
}

viewport prop

Viewport prop is used in conjunction with the whileInView prop to customize the behavior of the scroll trigger animation. The viewport prop takes an object with various properties to control how and when the animation is triggered.

  • amount: This property defines how much of the element needs to be in the viewport before the animation is triggered. It can take values like 0, 0.5, or 1. For example, if you set amount: 0.5, the animation will trigger when half of the element is visible in the viewport.

  • once: This property is a boolean that determines whether the animation should only play once when the element first comes into view. If set to true, the animation will not replay if the user scrolls away and then back to the element.

Example:

import { motion } from "framer-motion";
export default function App() {
    return (
        <div style={{ height: "150vh", padding: "50px" }}>
        <motion.div
            style={{
            width: 100,
            height: 100,
            backgroundColor: "blue",
            margin: "0 auto",
            }}
            initial={{ scale: 1, rotate: 0 }}
            whileInView={{ scale: 1.5, rotate: 90 }}
            transition={{ duration: 0.5 }}
            viewport={{ amount: 0.5, once: true }} // Animation triggers when half of the element is in view and plays only once
        />
        </div>
    );
    }

Using Variants with whileInView

In whileInView we can also use variants to define the animation states and then use the variant names in the whileInView prop.

import { motion } from "framer-motion";
export default function App() {
  return (
    <div style={{ height: "250vh", padding: "50px" }}>
      <div className="h-[150vh]"></div>

      <motion.div
        style={{
          width: 300,
          height: 300,
          backgroundColor: "blue",
          margin: "0 auto",
        }}
        variants={{
          initial: { scale: 1, opacity: 0, rotate: 0, borderRadius: "0%" },
          whileInView: { scale: 1.5, opacity: 1, borderRadius: "50%" },
        }}
        viewport={{
          amount: 0.3,
        }}
        initial="initial"
        whileInView="whileInView"
        // animate={{ scale: 1, rotate: 0 }}
        transition={{ duration: 5, staggerChildren: 0.5 }}
      >
        <motion.div
          className="h-10 w-10 bg-red-500 mt-10"
          variants={{
            initial: { x: 0, y: 0, rotate: 0 },
            whileInView: { x: 200, y: 100, rotate: 360 },
            transition: { duration: 2 },
          }}
        ></motion.div>

        <motion.div
          className="h-10 w-10 bg-red-500 mt-10"
          variants={{
            initial: { x: 0, y: 0, rotate: 0 },
            whileInView: { x: 200, y: 100, rotate: 360 },
            transition: { duration: 2 },
          }}
        ></motion.div>
      </motion.div>
    </div>
  );
}