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.
Turning a styled-component into something animatable <some html element> to start using Framer Motion for that component. Animating it's as easy as adding the animate , transition , and other props you're used to adding directly to motion elements.
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>
);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With