Stop 06 · Browser APIsTopics · 5/13

Intersection Observer

Part of the Frontend Developer Roadmap

In short

Lazy-loading images, infinite scroll, animations that start when you scroll to them. They all need to know 'is this element on screen yet?'. Intersection Observer answers that cheaply.

An efficient browser API for detecting when an element enters or leaves the viewport — powers lazy-loading, infinite scroll and scroll-triggered animations without expensive scroll listeners. It lets the browser efficiently determine visibility relationships without repeatedly calculating element positions inside high-frequency scroll handlers.

The jaadu mascot as a station master waves a green flag from a window as a train arrives.

Think of it like this

The station master's window

The station master doesn't run along the track checking every train. He sits at his window and reacts when a train enters the platform. Intersection Observer is that window: the browser tells you when an element enters or leaves view.

Watch it happen

A card scrolls into view

Your script
Observer
Card

observe(card)

1/5You hand the card to the observer once. No scroll listener, no maths.

The big ideas

What you need to know

Watches visibility

You pick elements to observe. The browser calls you when they cross into or out of the viewport.

No scroll math

No more scroll listeners and getBoundingClientRect on every scroll. The browser does the work efficiently.

threshold

threshold: 0.5 means 'tell me when half the element is visible'. 0 means any single pixel.

rootMargin

rootMargin: "200px" fires 200px before the element appears, handy for loading things early.

See it in code

Walk through the code

js
1const observer = new IntersectionObserver(2  (entries) => {3    for (const entry of entries) {4      if (!entry.isIntersecting) continue;5      entry.target.classList.add("fade-in");6      observer.unobserve(entry.target); // animate only once7    }8  },9  { threshold: 0.2, rootMargin: "0px 0px -50px 0px" }10);11 12document.querySelectorAll(".card").forEach((card) => observer.observe(card));

1/4The callback gets a list of entries. Skip any card that isn't on screen.

One observer can watch many elements. unobserve stops watching a card once it has animated, so the callback has less to do.

Save yourself the pain

Common mistakes

Oops

Using a scroll event listener that checks positions on every scroll.

Do this instead

Use IntersectionObserver. It's built for this and doesn't slow scrolling down.

Oops

Building lazy image loading from scratch for every <img>.

Do this instead

For plain images, loading="lazy" is built in. Use the observer for custom things like infinite scroll.

Your mission

Infinite scroll feed

~35 min

Quick check

What does threshold: 0.5 mean in IntersectionObserver options?

Go deeper

  1. 1Use it to lazy-load images only as they scroll into view. Verify the behavior with realistic data and handle the failure or empty state as well.
  2. 2Build a simple 'fade in on scroll' effect for page sections. Keep the first version small, then add one improvement after the core behavior works.
  3. 3Learn `threshold` and `rootMargin` options for fine-tuning when it triggers.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge