← CodeClarityLab Home
Browse by Category
+ added · updated 7d
← Back to glossary

Intersection Observer API

frontend ES2015 Intermediate

Also Known As

IntersectionObserver lazy loading scroll detection

TL;DR

A browser API that efficiently detects when elements enter or leave the viewport — replacing scroll event listeners for lazy loading, infinite scroll, and animation triggers.

Explanation

The Intersection Observer API calls a callback when a target element intersects with a root element (or the viewport). It is asynchronous and off the main thread — far more efficient than scroll event listeners which fire on every pixel of scroll. Use cases: lazy loading images, infinite scroll, triggering CSS animations when elements enter view, sticky header detection, and ad impression tracking. threshold (0.0-1.0) defines how much of the element must be visible to trigger, rootMargin pre-loads before the element is fully visible.

Common Misconception

Scroll event listeners are fine for detecting element visibility — scroll events fire hundreds of times per second on the main thread; Intersection Observer is asynchronous and does not block rendering.

Why It Matters

Scroll event listeners for visibility detection cause main thread jank — Intersection Observer is the standard, performant replacement that does not affect scroll performance.

Common Mistakes

  • Not disconnecting the observer after the element is loaded — the observer keeps running unnecessarily.
  • threshold: 1.0 for lazy loading — waits until the element is fully visible; use 0.1 to preload before it appears.
  • No rootMargin for lazy loading — images load exactly as they enter the viewport; add '200px' margin to preload ahead.
  • Using Intersection Observer for precise scroll position — it only fires at intersection thresholds, not on every pixel.

Code Examples

✗ Vulnerable
// Scroll event — main thread, fires hundreds of times per second:
window.addEventListener('scroll', () => {
    document.querySelectorAll('img[data-src]').forEach(img => {
        const rect = img.getBoundingClientRect();
        if (rect.top < window.innerHeight) {
            img.src = img.dataset.src; // Expensive DOM query on every scroll event
        }
    });
});
✓ Fixed
// Intersection Observer — async, efficient:
const observer = new IntersectionObserver((entries) => {
    entries.forEach(entry => {
        if (entry.isIntersecting) {
            const img = entry.target;
            img.src = img.dataset.src;
            observer.unobserve(img); // Stop observing once loaded
        }
    });
}, { rootMargin: '200px', threshold: 0.1 }); // Preload 200px before visible

document.querySelectorAll('img[data-src]').forEach(img => observer.observe(img));

Added 15 Mar 2026
Edited 22 Mar 2026
Views 33
Rate this term
No ratings yet
🤖 AI Guestbook educational data only
| |
Last 30 days
0 pings W 0 pings T 0 pings F 3 pings S 0 pings S 1 ping M 0 pings T 0 pings W 0 pings T 0 pings F 1 ping S 0 pings S 0 pings M 0 pings T 0 pings W 3 pings T 0 pings F 3 pings S 0 pings S 0 pings M 0 pings T 0 pings W 0 pings T 0 pings F 2 pings S 0 pings S 0 pings M 1 ping T 0 pings W 1 ping T
No pings yesterday
Amazonbot 13 Perplexity 5 Google 4 Ahrefs 2 ChatGPT 2 Majestic 1
crawler 25 crawler_json 1 pre-tracking 1
DEV INTEL Tools & Severity
🟡 Medium ⚙ Fix effort: Low
⚡ Quick Fix
Replace scroll event listeners with IntersectionObserver for lazy loading, infinite scroll, and animation triggers — it runs off the main thread with zero scroll performance impact
📦 Applies To
javascript ES2015 web
🔗 Prerequisites
🔍 Detection Hints
window.addEventListener('scroll') for lazy loading or visibility detection — should use IntersectionObserver
Auto-detectable: ✓ Yes lighthouse eslint
⚠ Related Problems
🤖 AI Agent
Confidence: Low False Positives: High ✗ Manual fix Fix: Low Context: File

✓ schema.org compliant