Framer motion animate when element is in-view (When you scroll to element)

14,118

framer-motion has built-in support for this use case since version 5.3.

Here's a CodeSandbox demonstrating the pattern: https://codesandbox.io/s/framer-motion-animate-in-view-5-3-94j13

Relevant code:

function FadeInWhenVisible({ children }) {
  return (
    <motion.div
      initial="hidden"
      whileInView="visible"
      viewport={{ once: true }}
      transition={{ duration: 0.3 }}
      variants={{
        visible: { opacity: 1, scale: 1 },
        hidden: { opacity: 0, scale: 0 }
      }}
    >
      {children}
    </motion.div>
  );
}

Usage:

<FadeInWhenVisible>
  <Box />
</FadeInWhenVisible>

Previous versions:

You can currently use the imperative animation controls to achieve this effect. Intersection observers are useful to detect if an element is currently visible.

Here's a CodeSandbox demonstrating the pattern: https://codesandbox.io/s/framer-motion-animate-in-view-gqcc8.

Relevant code:

function FadeInWhenVisible({ children }) {
  const controls = useAnimation();
  const [ref, inView] = useInView();

  useEffect(() => {
    if (inView) {
      controls.start("visible");
    }
  }, [controls, inView]);

  return (
    <motion.div
      ref={ref}
      animate={controls}
      initial="hidden"
      transition={{ duration: 0.3 }}
      variants={{
        visible: { opacity: 1, scale: 1 },
        hidden: { opacity: 0, scale: 0 }
      }}
    >
      {children}
    </motion.div>
  );
}
Share:
14,118
Ali Elkhateeb
Author by

Ali Elkhateeb

Updated on June 16, 2022

Comments

  • Ali Elkhateeb
    Ali Elkhateeb almost 2 years

    Is there any built-in way to make the animation start when the element is in-view (for example, when we scroll to the element)?

    Framer Motion has mount animations section which says:

    When a component mounts, it'll automatically animate to the values in animate if they're different from those defined in style or initial

    So I couldn't really find a straight forward way to make the animation start when it comes into view.

    However, I reached the only option I see for now is using Animation Controls which means I'll have to implement a listener on the scroll manually and trigger the control.start(), any easier ways are much appreciated.