Using the Intersection Observer API in JavaScript is a powerful way to detect when an element enters or exits the viewport. This can be useful for lazy loading images, infinite scrolling, or triggering animations when elements become visible on the screen.
Here is a simple custom helper that makes it easy to use the Intersection Observer API in JavaScript or TypeScript. The useIntersectionObserver
function takes a target element, a callback function to be called when the element intersects with the viewport, and an optional set of options to configure the observer.
export interface IntersectionObserverOptions {
/**
* The Element or Document whose bounds are used as the bounding box when testing for intersection.
* 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.
*/
root?: Element | Document
/**
* A string which specifies a set of offsets to add to the root's bounding_box when calculating intersections.
*/
rootMargin?: string
/**
* Either a single number or an array of numbers between 0.0 and 1.
* A threshold of 1.0 means that when 100% of the target is visible within the element specified by the root option, the callback is invoked.
*/
threshold?: number | number[]
}
export function useIntersectionObserver(
target: Element,
callback: IntersectionObserverCallback,
options: IntersectionObserverOptions = {}
): { isSupported: boolean; stop: () => void } {
const { root, rootMargin = '0px', threshold = 0.1 } = options
const isSupported = window && 'IntersectionObserver' in window
if (!isSupported) {
return { isSupported, stop: () => {} }
}
const observer = new IntersectionObserver(callback, {
root,
rootMargin,
threshold,
})
observer.observe(target)
return {
isSupported,
stop: () => {
observer.unobserve(target)
},
}
}
Usage example
Here is an example of how you can use the useIntersectionObserver
function to detect when an element enters or exits the viewport:
import { useIntersectionObserver } from './use-intersection-observer'
const targetElement = document.querySelector('.target-element')
const callback: IntersectionObserverCallback = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
console.log('Element is in the viewport')
} else {
console.log('Element is out of the viewport')
}
})
}