# Intersection Observer

The Intersection Observer API provides a way to asynchronously observe changes in the intersection of a target element with an ancestor element or with a top-level document's viewport.

## 1. The Concept

Historically, detecting when an element became visible (for lazy loading or infinite scroll) required event handlers on the main thread (like `scroll` or `resize`) and calling `getBoundingClientRect()`. This was slow and caused performance issues.

Intersection Observer offloads this to the browser, which can optimize it and run it off the main thread.

## 2. Basic Usage

To use it, you create a new `IntersectionObserver` object, passing it a callback function and an optional options object.

```javascript
const observer = new IntersectionObserver((entries, observer) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      console.log('Element is visible!');
      // Stop observing if needed
      // observer.unobserve(entry.target);
    }
  });
});

const target = document.querySelector('#target');
observer.observe(target);
```

## 3. Options

You can customize when the callback is invoked.

```javascript
const options = {
  root: null,        // The viewport (null = browser viewport)
  rootMargin: '0px', // Margin around the root (like CSS margin)
  threshold: 0.5     // Callback runs when 50% of target is visible
};

const observer = new IntersectionObserver(callback, options);
```

*   **`root`**: The element that is used as the viewport for checking visibility of the target. Must be the ancestor of the target. Defaults to the browser viewport if not specified or if `null`.
*   **`rootMargin`**: Margin around the root. Can have values similar to the CSS margin property, e.g. "10px 20px 30px 40px" (top, right, bottom, left). This set of values serves to grow or shrink each side of the root element's bounding box before computing intersections.
*   **`threshold`**: Either a single number or an array of numbers which indicate at what percentage of the target's visibility the observer's callback should be executed.

## 4. Use Cases

### Lazy Loading Images

```javascript
const images = document.querySelectorAll('img[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));
```

[[programming/javascript/vanilla/javascript]]
[[programming/javascript/vanilla/dom-manipulation]]
[[programming/javascript/vanilla/events]]