I am using framer motion to create a staggerd effect where 2 images slide in from the left.
It works perfect if im in the correct view port and refresh the screen.
However, if I scroll down to the elements, if I scroll slowly the first image willanimate, and the second won't untill I scroll down a bit further.
I think the bug is because there not in the same viewport at the same time.
How can I fix this by using a wrapper container or something?
"use client";
import { motion } from "framer-motion";
const variants = {
initial: {
opacity: 0,
transform: 'translateX(-150px)',
// filter: 'blur(5px)'
},
animate: (index: number) => ({
opacity: 1,
transform: 'translateX(0px)',
// filter: 'blur(0px)',
transition: {
duration: 1,
ease: 'easeInOut',
delay: 0.3 * index,
}
})
};
const FramerAnimationSlideIn = ({ items }: any) => {
return (
// @ts-ignore
items.map((item, index) => (
<motion.div
variants={variants}
initial="initial"
whileInView="animate"
key={item.src}
viewport={{
once: true,
}}
custom={index}
>
{item}
</motion.div>
)))
}
export default FramerAnimationSlideIn;
Because you have the whileInView
prop on each item element, the elements wil animate individually, and only when the element is in view. You are correct in that you need to add a wrapping div to use as the viewport trigger so all the elemet's animations fire at the same time.
Framer Motion provides a isInView
hook that can be used to help in this situation. When the container element is in view, we can tell each of the elemets to animate:
const FramerAnimationSlideIn = ({ items }: { items: Array<any> }) => {
const ref = useRef(null);
const isInView = useInView(ref, { once: true });
return (
<div ref={ref}>
{items.map((item, index) => (
<motion.div
key={index}
variants={variants}
initial="initial"
// Animate when the container is in view
animate={isInView && 'animate'}
custom={index}
>
{item}
</motion.div>
))}
</div>
);
};
You can customize the behavior with different options, similarly to how you would change the viewport
prop on motion elements.
Here is a working example.