Docs
README
19.3 Intersection Observer
Overview
IntersectionObserver efficiently tracks when elements enter or exit the viewport or another element's visible area.
How Intersection Observer Works
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā Intersection Observer ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā¤
ā ā
ā Viewport (Root) ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā ā ā
ā ā āāāāāāāāāāā ā ā
ā ā ā Element ā ā intersectionRatio: 1.0 (fully visible) ā ā
ā ā āāāāāāāāāāā ā ā
ā ā ā ā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā āā ā
ā ā āāāāāāāāāāā ā ā
ā ā ā Element ā ā intersectionRatio: 0.5 (half visible) ā ā
ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā
ā ā ā ā
ā āāāāāāāāāāā ā intersectionRatio: 0 (outside viewport) ā
ā ā
ā āāāāāāāāāāā ā
ā ā Element ā ā Not yet observed (outside) ā
ā āāāāāāāāāāā ā
ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Configuration Options
| Option | Type | Default | Description |
|---|---|---|---|
root | Element/null | null (viewport) | Container to check intersection against |
rootMargin | string | "0px" | Margin around root (like CSS margin) |
threshold | number/number[] | 0 | Intersection ratios to trigger callback |
IntersectionObserverEntry Properties
| Property | Description |
|---|---|
boundingClientRect | Target's bounding box |
intersectionRatio | Ratio of intersection (0-1) |
intersectionRect | Area of intersection |
isIntersecting | Whether target is intersecting |
rootBounds | Root's bounding box |
target | The observed element |
time | Timestamp of intersection |
Threshold Examples
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā threshold: [0] ā Callback when ANY part enters/exits ā
ā threshold: [0.5] ā Callback when 50% visible ā
ā threshold: [1.0] ā Callback when 100% visible ā
ā threshold: [0, 0.5, 1.0] ā Callback at 0%, 50%, and 100% ā
ā threshold: [0.25, 0.5, 0.75, 1.0] ā Fine-grained tracking ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
Basic Usage
// Create observer
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log('Element visible:', entry.target);
console.log('Visibility:', entry.intersectionRatio);
}
});
},
{
root: null, // viewport
rootMargin: '0px',
threshold: 0.5, // 50% visible
}
);
// Observe elements
observer.observe(element);
// Stop observing
observer.unobserve(element);
observer.disconnect();
Common Use Cases
- ā¢Lazy Loading: Load images/content when near viewport
- ā¢Infinite Scroll: Load more content at page bottom
- ā¢Analytics: Track which content users actually see
- ā¢Animations: Trigger animations on scroll
- ā¢Ad Viewability: Track if ads are actually seen
Summary
- ā¢More performant than scroll event listeners
- ā¢Asynchronous and non-blocking
- ā¢Can observe multiple elements efficiently
- ā¢Use rootMargin for preloading content
- ā¢Multiple thresholds for fine-grained control