Introduction
The Intersection Observer API has many practical uses (like this table of contents if you're on desktop!).
It 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.
Reference[1]
Browser Support
For most modern browsers, the Intersection Observer API is well-supported. However, it's worth noting that this API is not supported in Internet Explorer.
Check out the list of supported browsers.
If you need to support IE, you can consider using a polyfill for the Intersection Observer API. A polyfill is a piece of code that provides the technology that you expect the browser to provide natively.
However, keep in mind that while a polyfill can help bridge the gap for unsupported browsers, it may not offer the same performance benefits as the native API.
Polyfills typically can't leverage browser optimizations in the same way that native APIs can, which can lead to slower performance.
Performance Impact
Let's say you're working on a feature where you need to display or change the content of a page when a certain element becomes visible in the viewport.
This could be a 'load more' feature, an animation trigger, or a variety of other interactive experiences.
You might approach this using scroll events and the getBoundingClientRect
method, something like this:
This approach works, but it can be resource-intensive as it's constantly checking the position of the element during scroll events, which can lead to less-than-smooth animations or interactions.
Let's consider the performance benefits of using the Intersection Observer API:
Feature | Intersection Observer | Scroll Event Listener |
---|---|---|
Main Thread | Runs off the main thread, doesn't block other tasks. | Runs on the main thread, can block other tasks. |
Overhead | Efficiently tracks visibility of elements, runs only when visibility changes. | Checks position of elements on every scroll event, can be resource-intensive. |
Browser Optimization | Can be optimized by browsers, e.g., doesn't run when page is offscreen or minimized. | Can't be optimized in the same way, runs every time a scroll event occurs. |
Ease of Use | Easier to use, requires less code for tracking visibility of elements. | Can require more code and be more complex to implement. |
Intersection Observer API
Syntax Overview
Here's a basic example of how to use the Intersection Observer API:
Using requestIdleCallback
The Intersection Observer API specification suggests using requestIdleCallback()
to defer non-essential work.
This method allows you to schedule a function to be called during the browser's idle periods, which can help to improve performance by reducing the load on the main thread[2].
In the context of Intersection Observer, you might use requestIdleCallback()
in your callback function to defer tasks that don't need to happen immediately.
This could be particularly useful when you're dealing with a large number of elements or complex animations that could potentially cause jank.
Here's an example of how you might use requestIdleCallback()
with Intersection Observer:
This allows you to perform background or low priority work on the main event loop, without impacting latency-critical events such as animation and input response.
Options Param
Options Syntax Overview
The options parameter in the Intersection Observer API is an object that allows you to customize the way the observer works. It can have the following properties: root
, rootMargin
, and threshold
.
Code will be provided in the next section.
Root
The root
option in the Intersection Observer API refers to the element that is used as the viewport for checking the visibility of the target element[3];
If not specified or if set to null, it defaults to the browser viewport.
For example, if you want to observe when an element becomes visible within a scrolling div, you would set the root to that div.
Thresholds
The threshold
option is a number or an array of numbers between 0.0
and 1.0
, which indicate at what percentage of the target's visibility the observer's callback should be executed [4].
For example, if you set a threshold of 0.5, the callback will run when 50% of the target is visible in the viewport (or root).
RootMargin
The rootMargin
option is a string with syntax similar to the CSS margin property.
For example, if you set a rootMargin
of 10px
, the callback will run when the target is within 10px
of the edge of the viewport (or root
).
It can be used to grow or shrink each side of the root
element's bounding box before computing intersections, effectively giving you a way to specify a "margin" for the root
(or viewport).
This table summarizes how positive and negative rootMargin
values influence the intersection area and the timing of the Intersection Observer's callback trigger:
rootMargin Value | Effect on Intersection Area | When Callback is Triggered |
---|---|---|
Positive | Expands the area | Before the target enters the viewport or after it starts to leave |
Negative | Shrinks the area | After the target is further into the viewport or before it starts to leave |
For instance, if we wanted to increase the top and bottom intersection areas by 15%:
Show Me The Code
Here's a Stackblitz sandbox with an example using IntersectionObserver
displaying an overlay over the intersecting area:
Viewport as Root
This example does not declare a root, so viewport is used instead:Open Editor 💻 - Intersection Observer w/o
root
With Root Element
Compare to a root element defined in options param:Open Editor 💻 - Intersection Observer w
root
Reference[5]
https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver ↩︎
https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback ↩︎
https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/root ↩︎
https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/thresholds ↩︎
https://developer.mozilla.org/en-US/docs/Web/API/IntersectionObserver/rootMargin ↩︎