Skip to main content
Piotr Majkutewicz
Back to Blog

Mastering the Intersection Observer API

The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with its parent or the viewport. This powerful API is perfect for implementing infinite scrolling, lazy loading images, or triggering animations when elements come into view.

Basic Implementation

javascript
const observer = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      console.log('Element is visible!');
      // Do something with the visible element
    }
  });
});

// Start observing an element
observer.observe(document.querySelector('.target'));

Configuration Options

The IntersectionObserver constructor accepts an options object with three main properties:

javascript
const options = {
  root: null, // Use viewport as root
  rootMargin: '0px', // Margin around root
  threshold: 0.5 // Trigger at 50% visibility
};

const observer = new IntersectionObserver(callback, options);

Practical Examples

1. Lazy Loading Images

Improve page load performance by loading images only when they're about to enter the viewport.

javascript
function lazyLoadImages() {
  const images = document.querySelectorAll('[data-src]');
  
  const imageObserver = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
      if (entry.isIntersecting) {
        const img = entry.target;
        img.src = img.dataset.src;
        img.removeAttribute('data-src');
        observer.unobserve(img);
      }
    });
  });

  images.forEach(img => imageObserver.observe(img));
}

2. Infinite Scroll

Load more content when the user scrolls near the bottom of the page.

javascript
function setupInfiniteScroll(loadMoreCallback) {
  const sentinel = document.querySelector('#sentinel');
  
  const observer = new IntersectionObserver((entries) => {
    if (entries[0].isIntersecting) {
      loadMoreCallback();
    }
  });

  observer.observe(sentinel);
}

3. React Hook Implementation

A reusable React hook for intersection observation.

typescript
const useIntersectionObserver = (options = {}) => {
  const [isVisible, setIsVisible] = useState(false);
  const elementRef = useRef(null);

  useEffect(() => {
    const observer = new IntersectionObserver(([entry]) => {
      setIsVisible(entry.isIntersecting);
    }, options);

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

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

  return [elementRef, isVisible];
};

Best Practices

  • Always clean up observers when they're no longer needed
  • Use appropriate threshold values for your use case
  • Consider using rootMargin to pre-load content
  • Be mindful of the number of observed elements
  • Test on different viewport sizes and devices

Browser Support

The Intersection Observer API is widely supported in modern browsers. For older browsers, a polyfill is available. Check browser support before implementation.