🔮 Sanity Create is here. Writing is reinvented. Try now, no developer setup

Using framer-motion and react-intersection-observer to fade in images on load and scroll

14 replies
Last updated: Mar 15, 2022
hello! someone has an example or plugin to fadein next/images when loads ?
Mar 12, 2022, 12:40 AM
nice! I’ll give it a closer 👀
user E
Mar 12, 2022, 1:45 AM
What was the answer to this?
Mar 13, 2022, 1:41 AM
user M
I make it works using framer-Motion connected with two useState one to trigger when my image is loaded and another useState to trigger when my image is on the viewport.
• framer-motion for the animation job
• react-intersection-observer for the element in viewport true/false
• onLoadingComplete from next/image to set true/false
thanks for the suggestion
user E
🙏
Mar 14, 2022, 3:31 AM
user S

You don't need to use react-intersection-observer for this, take a look at
https://www.framer.com/docs/examples/#scroll-triggered-animations and whileInView and viewport.
Sample:


const bounceVariants: Variants = {
  offscreen: {
    y: 100,
    opacity: 0
  },
  onscreen: {
    y: 0,
    opacity: 1,
    transition: {
      type: "spring",
      bounce: 0.3,
      duration: 1.0
    }
  }
};

const BounceInScroll = ({ children}) => (
  <motion.div
    initial="offscreen"
    whileInView="onscreen"
    viewport={{ once: true, amount: 0.4 }}  
    data-testid="bounceinscroll"
  >
    <motion.div variants={bounceVariants}>{children}</motion.div>
  </motion.div>
);

Mar 14, 2022, 5:41 PM
This is so nice!! way less code to handle 🙌
Mar 14, 2022, 6:43 PM
import { motion } from "framer-motion";

const FadeElement = ({ children, hasBeenLoaded, getIndex }) => {
  return (
    <motion.div
      initial={{ opacity: 0 }}
      whileInView={{ opacity: hasBeenLoaded ? 1 : 0 }}
      transition={{ duration: 0.2, delay: getIndex * 0.1 }}
      viewport={{ once: true }}
    >
      {children}
    </motion.div>
  );
};

export default FadeElement;
Mar 14, 2022, 7:01 PM
What's hasBeenLoaded?
Mar 14, 2022, 7:03 PM
is for when next/image set true to
onLoadingComplete
Mar 14, 2022, 7:04 PM
probably this is pretty messy, but can give you a better perspective, I started to read about react and next just a month ago 👶

const Thumbnails = () => {
  const [loaded, setLoaded] = useState(false);
  return (
    <FadeElement hasBeenLoaded={loaded} getIndex={id}>
      <Image
        src={urlFor(mainImage).url()}
        alt="alt"
        layout="fill"
        loading="lazy"
        objectFit="cover"
        onLoadingComplete={() => setLoaded(true)}
      />
    </FadeElement>
  );
};

export default Thumbnails;
Mar 14, 2022, 7:13 PM
I don't think you need the hasBeenLoaded, you can just animate it when it it comes into scroll view, though
Mar 14, 2022, 7:16 PM
I don't think you need the hasBeenLoaded, you can just animate it when it it comes into scroll view, though
Mar 14, 2022, 7:16 PM
interesting, makes kind of sense! I’ll make a few tests.. my question is what happens if the motion.div is inside the viewport but the image is still loading
Mar 14, 2022, 7:20 PM
I'm no framer expert, you have to experiment and try it out yourself. 😉
Mar 14, 2022, 9:17 PM
Woah thanks so much!
Mar 15, 2022, 2:10 AM

Sanity– build remarkable experiences at scale

Sanity is a modern headless CMS that treats content as data to power your digital business. Free to get started, and pay-as-you-go on all plans.

Was this answer helpful?