intermediate

IntersectionObserver

Observe visibility changes for lazy loading, infinite scroll, analytics, and prefetching without scroll polling.

IntersectionObserver reports when a target crosses visibility thresholds relative to a root. It replaces many scroll polling patterns for lazy images, infinite lists, analytics impressions, and prefetch triggers. Correct usage defines root, rootMargin, thresholds, and cleanup while accepting that callbacks are asynchronous observations.

					const observer = new IntersectionObserver(
  (entries) => {
    for (const entry of entries) {
      if (entry.isIntersecting) loadImage(entry.target);
    }
  },
  { rootMargin: '200px 0px', threshold: 0.01 }
);
				

rootMargin preloads before visible pixels; thresholds control how much overlap counts. Unobserve when done to avoid leaks on long-lived SPAs.

On interviews: why it is usually cheaper than manual scroll listeners and how rootMargin changes preload timing.

Common pitfalls: it is not a precise animation clock. Forgetting to unobserve targets can leak observers in long-lived screens.

The trade-off is convenience versus control — pick the mechanism that matches your coupling and performance budget.

Checklist:

  • Set root, margin, and thresholds deliberately.
  • Unobserve or disconnect on teardown.
  • Do not assume frame-perfect timing.
  • Prefer native loading="lazy" when sufficient.