How To Do A Landing Page Fade-In

March 13, 2024

It seems every landing page I encounter has fade-in sections.

You know the one I mean. Scroll a bit, the next section magically comes into view through the mist, as if it were Arwen from Lord of the Rings and you caught her just as her dress fell from her shoulders. She takes her first brazen steps into the water, pausing, she glances over her right shoulder. You see a smirk. "Really think I didn't know you were there?"

...

So how do they do it!

We'll it's actually really easy, at least now, everything is handled by the IntersectionObserver API. It's a wonderful API, basically anything that involves figuring out if an HTML element has been encountered can be done with it:

  • Infinite scrolling
  • Lazy image loading
  • Seeing is someone is actually interested in an ad
  • ...

Oh, look at that, I've added it to this blog post:

<FadeIn>
- Infinite scrolling
- Lazy image loading
- Seeing is someone is actually interested in an ad
- ...
</FadeIn>

By the way, this blog is written in MDX, which is Markdown + React components.

The code:


"use client"
import React, { useRef, useEffect, useState } from 'react';

const FadeIn = ({ children, threshold = 0.5 }) => {
  const [isVisible, setIsVisible] = useState(false);
  const ref = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(
      (entries) => {
        if (entries[0].isIntersecting) {
          setIsVisible(true);
          observer.disconnect();
        }
      },
      { threshold }
    );

    if (ref.current) {
      observer.observe(ref.current);
    }

    return () => {
      if (ref.current) {
        observer.unobserve(ref.current);
      }
    };
  }, [ref, threshold]);

  return (
    <div
      ref={ref}
      style={{
        opacity: isVisible ? 1 : 0,
        transform: isVisible ? 'translateY(0)' : 'translateY(10px)',
        transition: 'opacity 1s ease-in-out, transform 1s ease-in-out',
      }}
    >
      {children}
    </div>
  );
};

export default FadeIn;

A few things to grasp:

  • The interaction observer checks if we're looking at that HTML element. The threshold value, 0.5 in this case, determines what determines what percentage, in this case 50%, of the aforementioned HTML element needs to be visible for setIsVisible(true) to be called.
  • A CSS transition is used for the fade-in. The interaction observer doesn't have anything to do fade-in directly. It simply figures out when the fade-in should occur.
That's it.