Intersection Observer API in JavaScript

Intersection Observer API in JavaScript

Description
The Intersection Observer API provides an asynchronous way to observe the intersection status of a target element with its ancestor element or the viewport. It can efficiently monitor whether an element enters or leaves the visible area, and is commonly used to implement features such as lazy loading of images, infinite scrolling, and exposure tracking.

Core Concepts

  1. Intersection Ratio: The ratio of the intersection area between the target element and the root element to the total area of the target element.
  2. Threshold: The intersection ratio value that triggers the callback function.
  3. Root Element: The ancestor element used as the reference frame, defaulting to the browser viewport.

Creating an Observer

// Create an observer instance
const observer = new IntersectionObserver(callback, options);

Detailed Explanation of Options Configuration

const options = {
  root: null,           // Root element, null means viewport
  rootMargin: '0px',    // Margin around the root element, used to expand or shrink the intersection area
  threshold: [0, 0.5, 1] // Threshold values that trigger the callback when the intersection ratio reaches them
};

Callback Function Structure

const callback = (entries, observer) => {
  entries.forEach(entry => {
    // entry contains intersection information of the target element
    console.log(entry.target);        // The observed element
    console.log(entry.isIntersecting); // Whether it is within the intersection area
    console.log(entry.intersectionRatio); // Current intersection ratio
  });
};

Complete Usage Example: Lazy Loading Images

// Create an observer
const lazyImageObserver = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      // Assign the value of data-src to src
      img.src = img.dataset.src;
      // Stop observing after the image loads
      img.onload = () => observer.unobserve(img);
    }
  });
}, {
  threshold: 0.1, // Load when 10% of the image enters the viewport
  rootMargin: '50px' // Start loading 50px in advance
});

// Observe all lazy-loading images
document.querySelectorAll('img[data-src]').forEach(img => {
  lazyImageObserver.observe(img);
});

Advanced Application: Infinite Scrolling

let page = 1;
const sentinel = document.getElementById('sentinel'); // Sentinel element

const infiniteScrollObserver = new IntersectionObserver(async (entries) => {
  if (entries[0].isIntersecting) {
    // Load more content
    const newContent = await loadMoreContent(page++);
    appendContent(newContent);
  }
});

infiniteScrollObserver.observe(sentinel);

Performance Advantages

  1. Asynchronous Execution: Does not block the main thread.
  2. Batch Processing: Multiple intersection changes are handled in a single callback.
  3. Automatic Optimization: The browser internally optimizes intersection detection.

Notes

  1. After creating the observer, you need to manually call observe() to start observing.
  2. Use unobserve() to stop observing a specific element.
  3. Use disconnect() to stop all observations.
  4. The root element must be an ancestor of the target element.

The Intersection Observer API solves performance issues related to scrolling and is an important tool in modern web development.