Infinite scroll pagination is inspired by websites such as Facebook and Twitter. This is just pagination where as the user scrolls to the bottom of the page, more content is loaded. This improves the user experience on the website by making sure there is always more content on the page for users to read.
Doing Infinite Scroll Pagination Right
When infinite scroll pagination is implemented, there are a few really important points to remember.
1. Don’t Put Important Links at the Bottom
Important links should not be at the bottom of the page. This is because every time the user tries to scroll down to find them, a new set of entries will load. All important links should be fixed on a sidebar or permanently kept on the top.
2. Plan Ahead
It’s important that you plan where you want to include pagination and how you are going to process it. A common way of doing pagination is by listing the page numbers at the bottom of the page. When you use the infinite scroll method, however, no more page numbers will appear at the end of your article list, as they’re no longer needed. This pagination can be used on all themes as long as you don’t include loads of information in your footer section, as it may not give the desired effect.
In this tutorial, we are going to learn how to implement the infinite scroll feature in JavaScript.
The page will display a list of fun facts about cats, which will come from an API. The API returns 10 fun facts by default. When you scroll to the bottom of the page, the application will display an indicator to denote the loading state of the app. Meanwhile, the app will call the API to load the next set of fun facts.
We are going to use this URL for loading fun facts. The API accepts a query string, page
, which tells the API which page to load.
https://catfact.ninja/facts?page=${page}&limit=${limit}
Now, let’s get started with the application.
1. Create the Project Structure
First, create a folder with the following structure.
root -- index.html -- style.css -- app.js
2. Build the HTML File
We are going to have several sections in our HTML file:
- a
container
, where the whole scrollable list of fun facts will be rendered - a
quotes
section for every fun fact - a
loader
, which will be visible when the fun facts are loading. Theloader
will be invisible by default.
<div class="container"> <h1>Fun Facts about Cats</h1> <div class="facts"> </div> <div class="loader"> <div></div> <div></div> <div></div> </div> </div>
3. Build the Script
Next, we need to create a script, which will connect with the div and load the fun facts. To achieve this, we will use the querySelector()
.
const factsEl = document.querySelector('.facts'); const loader = document.querySelector('.loader');
We also need a few control variables to define which set of items will be shown on the screen. The control variables in this snippet of code are:
-
currentPage
: The current page is initialised to 1. When you scroll to the bottom of the page, the current page will be incremented by 1, and an API request will be made to get the contents of the next page. When the page is scrolled to the top, the current page will be decremented by 1. -
total
: This variable stores the total number of quotes returned by the Fun Facts API.
4. Build the getFacts
Function
The role of the getFacts
function is to call the API and return the fun facts. The getFacts
function accepts a single argument: page
. It uses the Fetch API mentioned above to fetch data for the infinite scroll.
Fetch
always returns a promise
, so we are going to use the await-async
syntax for receiving and processing the response. To get the json
data, we will use the json
()
function. The getFacts
function returns a promise, which will resolve and return the JSON.
const getfacts = async (page, limit) => { const API_URL = `https://catfact.ninja/facts?page=${page}&limit=${limit}`; const response = await fetch(API_URL); // handle 404 if (!response.ok) { throw new Error(`An error occurred: ${response.status}`); } return await response.json(); }
5. Build the showFacts
Function
Now that we have received the fun facts, where can we display these facts? This is why we need to have a showFacts
function. The showFacts
function works by iterating through the facts
array. Then, it uses the template literal
syntax to create an HTML representation of a fact
object.
const showfacts = (facts) => { facts.forEach(fact => { const factEl = document.createElement('blockfact'); factEl.classList.add('fact'); factEl.innerHTML = ` ${fact.fact} `; factsEl.appendChild(factEl); }); };
A sample of the generated blockFact
element is:
<blockfact class="fact"> Unlike dogs, cats do not have a sweet tooth. Scientists believe this is due to a mutation in a key taste receptor. </blockfact>
We make use of the appendChild
function to add the <blockfact>
element to the container.
6. Show and Hide the Loading Indicator
As the user reaches the end of the page, a loading indicator has to be shown. For this, we are going to introduce two functions: one for loading, and the other for hiding the loader. We will use opacity: 1
to show the loader and opacity: 0
to hide the loader. Adding and removing opacity
will show/hide the loader, respectively.
const hideLoader = () => { loader.classList.remove('show'); }; const showLoader = () => { loader.classList.add('show'); };
7. Check for More Fun Facts
To improve performance, we are going to introduce a function that can check if the API has more facts. The hasMoreFacts()
function will return true
if there are more items to fetch. If there are no more items to fetch, the API calls will stop.
const hasMorefacts = (page, limit, total) => { const startIndex = (page - 1) * limit + 1; return total === 0 || startIndex < total; };
8. Code the loadFacts
Function
The loadFacts
function is responsible for performing these important actions:
- show or hide the loading indicator
- call the
getFacts
function to fetch more facts - show the facts
const loadfacts = async (page, limit) => { // show the loader showLoader(); try { // if having more facts to fetch if (hasMorefacts(page, limit, total)) { // call the API to get facts const response = await getfacts(page, limit); // show facts showfacts(response.data); // update the total total = response.total; } } catch (error) { console.log(error.message); } finally { hideLoader(); } };
In a sense, a drawback of this implementation is how fast it runs. You will not see the loading indicator most of the time because the API can return very quickly. If you want to see the loading indicator with every scroll, a setTimeout
function can be used. Tweaking the delay
of your setTimeout
function will decide how long the loading indicator will be shown.
When the user scrolls to the bottom of the page, a scroll event handler
is required to call the loadFacts
function. The function will be called if the following conditions are met:
- the scroll has reached the bottom of the page
- there are more facts to be loaded
To achieve the scroll event, we will be making use of three window properties:
-
window.scrollHeight
gives the entire document’s height. -
window.scrollY
gives an account of how far the document was scrolled by the user. -
window.innerHeight
gives the height of the window that is visible.
The diagram below gives a better overview of the above properties. Also, you will be able to understand that, if the sum of innerHeight
and scrollY
is equal to or greater than scrollHeight
, the end of the document is reached, and this is when more fun facts have to be loaded.
window.addEventListener('scroll', () => { const { scrollTop, scrollHeight, clientHeight } = document.documentElement; if (scrollTop + clientHeight >= scrollHeight - 5 && hasMoreFacts(currentPage, limit, total)) { currentPage++; loadFacts(currentPage, limit); } }, { passive: true });
10. Initialise the Page
The last step in our infinite scroll would be to initialise the page. It is important to call loadFacts
to load the very first set of fun facts.
loadfacts(currentPage, limit);
Live Demo
Conclusion
Now, we have implemented a simple infinite scroll in JavaScript, which will fetch and render fun facts about cats whenever the user scrolls. This is just one of the most commonly used methods for infinite scrolling.