Building an Infinite Scroll Component with Intersection Observer 🚀
Vikas Choubey
Posted on March 2, 2024
In the realm of web design, user experience is paramount. Enter infinite scroll – a game-changing solution that seamlessly loads content as users scroll, eliminating the need for traditional pagination and offering a frictionless browsing experience.
We have a <div>
element with an id="content"
that contains some initial items (e.g., "Item 1", "Item 2", ...).
At the end of the content, there's a sentinel <div>
with the class sentinel
. This sentinel div is used as a trigger point for loading more items when it comes into view.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Pagination with Intersection Observer</title>
</head>
<body>
<div id="content">
<div class="item">Item 1</div>
<div class="item">Item 2</div>
<div class="item">Item 3</div>
<div class="item">Item 4</div>
<div class="item">Item 5</div>
<div class="item">Item 6</div>
<div class="item">Item 7</div>
<div class="item">Item 8</div>
<div class="item">Item 9</div>
<div class="item">Item 10</div>
<div class="sentinel"></div>
<!-- we will observe this element -->
</div>
</body>
</html>
CSS Styling:
Basic styling to remove default margin and padding, and to define the appearance of items and the sentinel div. 🎨
<style>
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.sentinel {
height: 20px;
background-color: transparent;
}
.item {
border: 1px solid #ccc;
padding: 20px;
margin-bottom: 10px;
}
</style>
JavaScript:
- We select the sentinel element using
document.querySelector('.sentinel')
. 🎯 - We define options for the Intersection Observer:
-
root
: The viewport. We set it to null to observe the document's viewport. 👀 -
rootMargin
: Margin around the root. We set it to 0px. 📏 -
threshold
: The percentage of the target element which should be visible before triggering the callback. We set it to 0.8, meaning the callback will be triggered when the sentinel element is 80% in view. 🚦
-
- We define the
handleIntersection
function, which will be called when the sentinel element intersects with the viewport.- It checks if the sentinel element is intersecting with the viewport using
entry.isIntersecting
. 🛑 - If it is intersecting, it calls the
loadMoreItems
function and stops observing the sentinel element. 🔄
- It checks if the sentinel element is intersecting with the viewport using
- We define the
loadMoreItems
function, which simulates loading more items:- It creates new
<div>
elements with the classitem
and adds them to the content area before the sentinel. 📦 - After loading more items, it re-observes the sentinel element. 🔄
- It creates new
- We create a new
IntersectionObserver
instance, passing in thehandleIntersection
function and options. 🕵️♂️ - Finally, we observe the sentinel element using
observer.observe(sentinel)
. 🚀
<script>
const content = document.getElementById("content");
const sentinel = document.querySelector(".sentinel");
const options = {
root: null,
rootMargin: "0px",
threshold: 0.8, // Trigger when the sentinel is 80% visible
};
function handleIntersection(entries, observer) {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setTimeout(loadMoreItems, 500); // mimic async call
}
});
}
function addElements(min, max){
for (let i = min; i <= max; i++) {
const newItem = document.createElement("div");
newItem.classList.add("item");
newItem.textContent = "Item " + i;
content.appendChild(newItem);
}
}
function loadMoreItems() {
// Simulate loading more items
const len = content.children.length;
content.removeChild(sentinel); // remove from current position
addElements(len, len+5)
content.appendChild(sentinel); // add before last 4 elements
addElements(len+6, len+10)
}
const observer = new IntersectionObserver(handleIntersection, options);
observer.observe(sentinel);
</script>
How it Works:
- Initially, the Intersection Observer is set up to observe the sentinel element.
- As the user scrolls down the page, when the sentinel element comes into view (i.e., when it intersects with the viewport), the
handleIntersection
function is called. - Inside
handleIntersection
, we load more items and stop observing the sentinel to prevent multiple triggerings. - After loading more items, we re-observe the sentinel so that the process can repeat when the user scrolls further down.
- This setup allows for a smooth and efficient implementation of pagination or infinite scroll on a web page. 🌟
Note: We removed the sentinel from its previous position and added it just before the last 4 new items, this way when user scrolls down our sentinel will be in viewport before the user sees the last 4 items and we will have time to load our next new items before user reaches the end of the list, this helps us make the user experience a little better as the user never has to wait for the next new items to load.
Connect with me on my:
Posted on March 2, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.