INFINITE SCROLL in JAVASCRIPT(Intersection Observer API) - Part 2
In part one I have covered infinite scroll on scroll event which is heavy performance wise. In this article we will look at the intersection observer api.
So let's dive right in..
The Intersection Observer API is a JavaScript API that provides a way to efficiently monitor changes in the intersection of an element with a specified target element or the viewport(viewport). It offers a mechanism to track when an element enters or exits the viewport or intersects with another element. This API is particularly useful for implementing lazy loading of images, infinite scrolling, animations triggered by scrolling, and other scenarios where you need to react to visibility changes of elements on a webpage without significantly impacting performance(intersection-observer-api).
This API has a disadvantage as well like browser compatibility because it is not available in older browsers but modern browsers support intersection observer api.
Now let's create an infinite scroll with intersection observer api, I will be using the same star wars api (https://swapi.dev/api/people/) for demonstration purpose. It is a public api anyone can access and it fetches the people associated with star wars like actors, directors etc.
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="styles.css" />
<script src="index.js" defer></script>
</head>
<body>
<div class="artist-container"></div>
</body>
</html>
CSS:
body {
background-color: white;
color: white;
}
h1 {
text-align: center;
}
.artist-container {
width: 75ch;
height: 75vh;
overflow-y: scroll;
margin: auto;
padding: 10px;
border-radius: 12px;
background-color: #001119;
}
.artist {
font-size: 18px;
margin: 16px;
padding: 10px;
border-top: 4px solid #11967e;
border-radius: 8px;
background-color: black;
}
JS:
Recommended by LinkedIn
const BASE_URL = "https://swapi.dev/api/people/";
let nextId = null;
let canFetchData = true;
let lastElement = document.querySelector(".artist:last-child");
const container = document.querySelector(".artist-container");
fetchData();
const handleIntersection = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// Element is now intersecting with the viewport or target.
observer.unobserve(lastElement);
fetchData();
}
});
};
const options = {
root: container,
threshold: 1,
};
const observer = new IntersectionObserver(handleIntersection, options);
async function fetchData() {
canFetchData = false;
const url = createApiURL();
const response = await fetch(url);
const data = await response.json();
const { results, next } = data;
const fragment = document.createDocumentFragment();
results.forEach(({ name }) => {
fragment.appendChild(createStarElement(name));
});
container.appendChild(fragment);
if (next) {
nextId = next[next.length - 1];
lastElement = document.querySelector(".artist:last-child");
observer.observe(lastElement);
}
canFetchData = true;
}
function createStarElement(name) {
const element = document.createElement("p");
element.textContent = name;
element.classList.add("artist");
return element;
}
function createApiURL() {
const url = new URL(BASE_URL);
if (nextId != null) {
url.searchParams.set("page", nextId);
}
return url;
}
Rest of the code is similar except below line:
const observer = new IntersectionObserver(handleIntersection, options);
We are creating an instance of IntersectionObserver and we pass it handleIntersection callback functions and options object.
handleIntersection: The handleIntersection parameter is a callback function that will be invoked whenever there is a change in the intersection status of the observed elements. This function is where you define what actions to take when an element enters or exits the viewport or intersects with another element. The callback function takes a list of IntersectionObserverEntry objects as its argument. Each entry object represents the state of an observed element in relation to the viewport or the target element. Example
const handleIntersection = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
observer.unobserve(lastElement);
fetchData();
}
});
};
The entry is an observed element and we check if the observed element is intersecting or not then write rest of the logic. The isIntersecting flag can tell whether the element that we observed is intersecting or not.
options: The options parameter is an object that allows you to customize the behavior of the IntersectionObserver. It includes various properties that define how the observer should behave. Some of the important properties are:
That's pretty much all in scope of this article, you can read more about intersection observer api on mdn docs. It is an important topic which is asked in machine coding rounds of many big tech companies.
Thank you,
Mohammad Izhan