Modern web applications use a lot of animations and media ranging from images, gif, videos to SVG’s to make user experience elegant and engaging. If not handled properly, it can hamper your website’s performance, and these things might not work in your favour. To overcome this issue of over-fetching resources, we need to handle the media on our website more sincerely and display them only when necessary, the jargon for which is lazy loading.
IntersectionObserver provides a way to asynchronously observe changes in the intersection of a target element with a wrapper element or with a top-level document's viewport.
Earlier, detecting visibility of an element, or the relative visibility of two elements with each other, was a difficult task and one would need event handlers and loops calling methods like Element.getBoundingClientRect().
The IntersectionObserver API provides a callback function that is executed whenever the element we wish to monitor enters or exits another element or the viewport.
Let’s test this thing out.
We will be using React for building the UI; however, the implementation is not React specific.
We will start by creating an IntersectionObserver by calling its constructor.
The constructor requires two arguments:
- callback function
The options argument is an object with values as given below:
The fields of options object are as follows:
- root: The element that is used as the viewport for checking the visibility of the target. If the value is provided as null or not specified, then it will take the browser’s viewport.
- rootMargin: This set of values serves to grow or shrink each side of the root element's bounding box before computing intersections. It accepts values in a similar fashion as CSS e.g. "5px 10px 5px 10px".
- 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. Its value ranges from 0 to 1.0, where 0 symbolises that one pixel is visible and 1.0 means every pixel is visible in the viewport.
Now we will select all target elements and observe them.
The next step is to define our callback function.
Whenever the target meets a threshold specified for the IntersectionObserver, the callback is invoked. The callback receives a list of IntersectionObserverEntry objects and the observer:
We will check if the entry(element) is intersecting and then we will replace the data-src attribute’s value with our <img /> tag’s source value.
The next step is to create our UI, which is built in React.
Here is how it will behave, and the images/videos will only be fetched when an element is in the viewport.
The above method we discussed is straightforward and can be implemented at any point in time in your project. Just a few lines of code and you have stopped over-fetching of resources.
I hope this blog was helpful in understanding how to improve the performance of media-heavy React applications using Intersection Observer pattern. If you'd like to improve your application's performance, reach out to [email protected] for a free consultation.