DOM Components

Infinite Scroll As A Design Pattern

How to use the browser's Intersection Observer for a positive user experience

by Joe Honton

At some point in our lives, most of us have whiled away the time reading one thing after another on the internet, as our fancy dictates. Lazy surfing the web is a pleasure all unto itself. No one knows what rabbit hole we may go down, or what pearls may be discovered through serendipity.

At one time it was considered a good practice in web design to provide an over-abundance of hyperlinks, to help readers navigate a website from page to page. This strategy was employed to guide readers toward related information, news or articles.

More recently though, that thinking has been refined. The new strategy has become more directed: make a call to action and point the user toward a single destination page.

But even that strategy has undergone refinement. The new design philosophy is to stay away from hyperlinks whenever possible, by presenting the user with an infinitely scrolling page containing more of what they've already demonstrated an interest in.

We've seen this strategy employed by more than just the big social media sites. For example, online retailers have discovered that paginated results provide too much friction for shoppers. If a shopper is looking for something, but doesn't find it on the first page of the results, there's a wariness about pressing a button to get the next 10 or 20 matches. Yet when retail sites present those same results using the infinite scroll design pattern, shoppers will doggedly stay with it. It seems that paginated results has become a design failure.


Implementing infinite scroll

Software developers wanting to implement infinite scroll can easily get started with the browser's IntersectionObserver callback function.

As a working example, we could create a component for use on a blogging site which automatically fetches the another article when the reader has reached the end of the original article.

Here's what the code looks like:

const observer = new IntersectionObserver((entries) => {
if (entries[0].isIntersecting == true) {
fetchNextArticle();
}
}, {threshold: 0});

const bottomOfPage = document.querySelect('#bottom-of-page');
observer.observe(bottomOfPage);

There isn't much to it. The bottom-of-page element could be any HTML element, but in its simplest form it is just a clear div, that has non-zero dimensions, situated somewhere after the original article's content.

The observer is called when the reader scrolls to a point where the target div becomes visible. A threshold value of 0 will trigger the callback when any part of the div is in the viewport. A threshold value of 1 will only trigger it when all of the div is in the viewport.

The fetchNextArticle function is where the just-in-time loading happens:

const articleUrls = [
'/feb-28-2021.html',
'/feb-21-2021.html',
'/feb-14-2021.html',
'/feb-07-2021.html'
];

const nextIndex = 0;

async fetchNextArticle() {
// fetch the article using HTTP
const response = await fetch(articleUrls[nextIndex++]);
if (response.status != 200 && response.status != 304)
return;
const templateText = await response.text();

// get the <body> of the article's HTML
const template = document.createElement('template');
template.innerHTML = templateText;
const body = template.content.querySelector('body');

// create a new <article> and insert it
const nextArticle = document.createElement('article')
nextArticle.innerHTML = body.innerHTML;
bottomOfPage.parentNode.insertBefore(nextArticle, bottomOfPage);
}

In this example, there are four articles that are queued for just-in-time loading. Of course in practice, that queue should be dynamically built to match the reader's interests.

This bare-bones example is a good starting point, but savvy developers can easily imagine improvements:

  • Querying the next article's <title> and <meta> tags to extract open graph data, like featured image, dateline, byline, and lede paragraph.
  • Removing unnecessary headers, footers, menus and advertising links from the article's <body>.
  • Giving the reader a way to toggle between two views of the article: a collapsed UI card and an expanded full-text view.

All of this has been implemented in the rwt-piqueme DOM component, which is ready-to-use via NPM.


Is infinite scroll here to stay?

Infinite scroll has been with us for more than ten years, so it's not a fad that's going away soon.

In fact, some people believe that this design pattern is too good and that it leads to addictive behavior and even doom scrolling. In July of 2019, Senator Josh Hawley cried foul and went so far as to introduce a bill in U.S. Congress that would ban infinite scrolling.

But most of us know our limits, and are savvy enough to know when to say "enough". I personally don't think this is an issue that politicians should be meddling with — they're tilting at windmills. I'd prefer to leave it to the psychology professionals to guide on such matters.

Infinite Scroll As A Design Pattern — How to use the browser's Intersection Observer for a positive user experience

🔎