Build Infinite Scroll With Vanilla JS + Web APIs — no library or framework.

Build Infinite Scroll With Vanilla JS + Web APIs — no library or framework.

Quick summaryInfinite scroll is a web design technique that loads more content automatically and continuously at the bottom when the user scrolls to the bottom of a page, eliminating the need to click/navigate to the next page. In this article I will explain how to build a simple image gallery with the infinite scroll without any use of a third party library or framework, only vanilla JavaScript.

“I want to load few contents when my application starts, then move on to loading the rest of it on user’s demand”

Introduction

According to MDN Web Docs , Infinite scrolling is when more and more contents are loaded and rendered as you scroll, so that the user doesn't have to flip through pages. This way only few contents are loaded at the Document Content Loaded Time — the average time (in seconds) that the browser takes to load into the web document’s content. This improves the application performance, user experience as well.

Creating contents on user’s demand is one of the approaches to help optimize user experience and web page performance. We structure the web contents to display when the user asks or needs to see them, either through an asynchronous request to a server for the contents or manually loading the contents.

A Case Study

When there’s large amount of contents to load/display to the users, the load time of these contents could be a challenge — slows down the application performance thereby affecting the user experience. When contents loads, the user sees only those that are visible on the viewport, and others that are not yet visible to the user also gets loaded for display. This wastes a lot of resources, especially time needed to load images — if available, and other data hungry contents.

Prerequisites

In this tutorial, you will need basic knowledge of:

  • HTML
  • JavaScript and the Web APIs.

Getting Started

In this section, we’d build the HTML structure of our application, here we will add the initial contents to be loaded before the application load time.

<!DOCTYPE html>
<html>
  <head>
    <link rel="stylesheet" href="./css/styles.css" />
    <meta charset="UTF-8" />
    <title>Dotch</title>
  </head>
  <body>
    <main class="container">
      <div class="first">
        <div class="img-container">
          <img
            src="./images/arctic-guesthouse-igloos-fEw9RsoDEq4-unsplash.jpg"
            alt="chris"
          />
        </div>
      </div>
      <div class="second">
        <div class="img-container">
          <img
            src="images/benigno-hoyuela-Z5PknsAvHkk-unsplash.jpg"
            alt="benigno"
          />
        </div>
      </div>
      <div class="third">
        <div class="img-container">
          <img src="./images/siri-louis-Qxr_U0KpdpA-unsplash.jpg" alt="siri" />
        </div>
      </div>
      <div class="third">
        <div class="img-container">
          <img
            src="./images/chris-ainsworth-jUR9ZFNqL-w-unsplash.jpg"
            alt="siri"
          />
        </div>
      </div>
      <div class="third">
        <div class="img-container">
          <img
            src="./images/josh-rocklage-MM5-DtrFLn0-unsplash.jpg"
            alt="siri"
          />
        </div>
      </div>
      <div class="third">
        <div class="img-container">
          <img
            src="./images/benjamin-massello-twX-cWl-8OM-unsplash.jpg"
            alt="siri"
          />
        </div>
      </div>
    </main>
    <div class="loading"></div>
  </body>
  <script src="./js/index.js" type="application/javascript"></script>
</html>

The above markup contains a simple main element that contains each image container, and the img elements nested within them. The <div class="loading"></div> markup after the closing main element will be used for animation which stimulates the asynchronous fetching of data from the server or the creation of more contents for display.

Implementing The Infinite Scroll

The logic relies on the scroll event that fires off on the window object, and with the help of some of the Web APIs. We put an event listener on the window object to help detect when the user scrolls.

window.addEventListener("scroll", dynamicPostUpdate);

The function dynamicPostUpdate checks if we have reached the end of the screen viewport with the help of some Web APIs — ---offsetHeight, pageYOffset, innerHeight. With offsetHeight we will get the height of the the main element, measured in pixels. The pageYOffset, tells us the number of pixels the document is currently scrolled along the vertical axis (that is, up or down) with an initial value of 0.0. The innerHeight. indicates the window's layout viewport height in pixels.

When the sum of pageYOffset and innerHeight is greater than or equal to the value of offsetHeight, then the end of the viewport is reached and the function dynamicPostUpdate implements the call to a custom function to manually load/create more contents and add them to the main element.

function dynamicPostUpdate() {
  let contentHeight = mainContainer.offsetHeight;
  let verticalOffset = window.pageYOffset;
  let verticalDistance = verticalOffset + window.innerHeight;
  if (verticalDistance >= contentHeight) {
    footerUI.style.display = "block";
    setTimeout(function () {
      footerUI.style.display = "none";
      createMoreContents();
    }, 3000);
  } else {
    footerUI.style.display = "none";
  }
}

The createMoreContent function manually creates more contents following the same pattern of the initially loaded contents at load time. These created contents are appended to the mainContainer, that’s the main element within the HTML file.

function createMoreContents() {
  let postsPerSeconds = randomDecision(5);
  for (let count = 0; count < postsPerSeconds; count++) {
    const generatedDIV = document.createElement("div");
    generatedDIV.id = imageData[randomDecision(imageData.length)].id;
    const imgContainer = document.createElement("div");
    imgContainer.className = "img-container";
    imgContainer.innerHTML = `<img src="./images/${
      imageData[randomDecision(imageData.length)].imageSrc
    }">`;
    generatedDIV.appendChild(imgContainer);
    mainContainer.appendChild(generatedDIV);
  }
}

Conclusion

In this tutorial, we have learnt about Infinite scroll and how to implement it in building a simple image gallery. To further improve the application, createMoreContent can be replaced with a request to server for data which is useful for any asynchronous operations. user events can be placed inside the if block of the dynamicPostUpdate function.

A live demo of what we built through the knowledge gained from this article can be found on Codesandbox . You can read more about infinite scroll on Web APIs here .