Infinite scrolling is now a common feature and there are several cases where it is really useful. For instance there are some websites where we simply can’t imagine a good pagination system, like Twitter or even Facebook. Another example of where infinite scrolling can be useful is for a search engine: you’ll want to continue viewing new links while you don’t find the one you want, and a pagination system can slow you down in your research.
If you need to use infinite scrolling for your project, here are six demos that you can use as inspiration to implement it.
Note that, except for the last one, all these demos are written with jQuery and some examples are using jQuery plugins. However, other examples can easily be adapted for vanilla JS without any problem.
1. Infinite Scrolling and Grids
This demo uses the jQuery Masonry plugin together with the Infinite Scroll plugin. The Masonry plugin is good for obtaining fluid grid layouts. The Infinite Scroll plugin by Paul Irish is good at loading pages that already exist (so it is good for your SEO). You can use it to load static pages such as page2.html
, page3.html
, etc., but this plugin also handle generated pages, such as page.php?p=2
, page.php?p=3
. However, to use it you need to have a page number to increment in your URLs so, if you have pages such as page.php?data=xxx
, then this plugin is not for you.
Usage – HTML
<div class="grid">
<div class="grid-item grid-item-2">
<p>content</p>
</div>
…
</div>
<!-- The next page which content will be loaded when scrolled -->
<nav id="pagination">
<p><a href="page-2.html">Page 2</a></p>
</nav>
Usage – jQuery
$(document).ready(function() {
var grid = $('.grid');
grid.masonry({
itemSelector: '.grid-item',
columnWidth: 200
});
grid.infinitescroll({
// Pagination element that will be hidden
navSelector: '#pagination',
// Next page link
nextSelector: '#pagination p a',
// Selector of items to retrieve
itemSelector: '.grid-item',
// Loading message
loadingText: 'Loading new items…'
},
// Function called once the elements are retrieved
function(new_elts) {
var elts = $(new_elts).css('opacity', 0);
elts.animate({opacity: 1});
grid.masonry('appended', elts);
});
});
2. Infinite Scrolling through Blog Posts
This demo doesn’t use any plugin or library to handle the infinite scrolling feature. Each time the end of the page is reached by the user, it loads a new post, generated by a PHP script that echoes the corresponding HTML code. The demo never reaches the end of content but you can achieve this by, for example, echoing an empty string when there is no more posts to show. We display a loading image at the end of the page, in the spirit of Twitter.
Note that, in the live demo below, the new posts are generated by a JavaScript function, as we can’t use a PHP script in CodePen.
See the Pen Infinite Scrolling through Blog Posts by SitePoint (@SitePoint) on CodePen.
Usage – HTML
<ul id="posts">
<li>
<article>content</article>
</li>
…
</ul>
<p id="loading">
<img src="images/loading.gif" alt="Loading…" />
</p>
Usage – jQuery
$(document).ready(function() {
var win = $(window);
// Each time the user scrolls
win.scroll(function() {
// End of the document reached?
if ($(document).height() - win.height() == win.scrollTop()) {
$('#loading').show();
$.ajax({
url: 'get-post.php',
dataType: 'html',
success: function(html) {
$('#posts').append(html);
$('#loading').hide();
}
});
}
});
});
3. Infinite Scrolling through Images
This demo loads in images on infinite scroll and never reaches the end. It uses the jQuery Endless Scroll plugin which can be customized to trigger loading x number of pixels from the bottom of the screen. The demo clones the same images and inserts them at the end of the list and so on, but the script can be customized to load the images from different sources quite easily.
See the Pen Infinite Scrolling through Images by SitePoint (@SitePoint) on CodePen.
Usage – HTML
<ul id="images">
<li>
<a href="https://www.pexels.com/photo/mist-misty-fog-foggy-7919/">
<img src="https://pexels.imgix.net/photos/7919/pexels-photo.jpg?fit=crop&w=640&h=480" alt="" />
</a>
</li>
…
</ul>
Usage – jQuery
$(document).ready(function() {
$(window).endlessScroll({
inflowPixels: 300,
callback: function() {
var $img = $('#images li:nth-last-child(5)').clone();
$('#images').append($img);
}
});
});
4. Infinite List of Numbers
This demo uses the same plugin as the previous one but we have applied the infinite scroll to a list with its own vertical scrollbar. As you scroll down the numbers are simply appended as list items.
See the Pen An infinite list of numbers by SitePoint (@SitePoint) on CodePen.
Usage – HTML
<ul id="numbers">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
…
</ul>
Usage – jQuery
$(document).ready(function() {
var offset = $('#numbers li').length;
$('#numbers').endlessScroll({
fireOnce: false,
fireDelay: false,
loader: '',
insertAfter: '#numbers li:last',
content: function(i) {
return '<li>' + (i + offset) + '</li>';
}
});
});
5. Infinite Spreadsheets
This demo uses the same technique as demo 2 to detect when the user has reached the end of the document, not just vertically but also horizontally. Each time one end is reached we add a new row or a new column to the table. It is exactly the kind of script we could write if we want to create a spreadsheets application.
Note that all the cells are empty. The rows and columns indexes are generated with CSS counters so that we don’t need to calculate them by ourselves.
See the Pen Infinite Spreadsheets by SitePoint (@SitePoint) on CodePen.
Usage – HTML
<table id="spreadsheet">
<tr>
<td></td>
<th></th>
…
</tr>
<tr>
<th></th>
<td></td>
…
</tr>
…
</table>
Usage – jQuery
$(document).ready(function() {
var win = $(window);
var doc = $(document);
// Each time the user scrolls
win.scroll(function() {
// Vertical end reached?
if (doc.height() - win.height() == win.scrollTop()) {
// New row
var tr = $('<tr />').append($('<th />')).appendTo($('#spreadsheet'));
// Current number of columns to create
var n_cols = $('#spreadsheet tr:first-child th').length;
for (var i = 0; i < n_cols; ++i)
tr.append($('<td />'));
}
// Horizontal end reached?
if (doc.width() - win.width() == win.scrollLeft()) {
// New column in the heading row
$('#spreadsheet tr:first-child').append($('<th />'));
// New column in each row
$('#spreadsheet tr:not(:first-child)').each(function() {
$(this).append($('<td />'));
});
}
});
});
6. Infinite Scrolling + Pagination
There are cons against infinite scrolling: if it is not implemented well, the user experience can be broken. If you let the user load an infinite list, they can lose their place after a while. That’s a thing that never appends with a traditional pagination system. However, pagination requires actions from the user that aren’t necessary with infinite scrolling.
These two facts gave Tim Severien an idea: what if we combined infinite scrolling and pagination, to take the advantage of both methods? The result is this last demo.
An initial page is shown to the user. When the user scrolls down and reaches the bottom of the page, a new page is loaded automatically. Here we enjoy the simplicity from infinite scrolling. But the new things come from a list fixed at the bottom of the screen.
Initially hidden, this list is filled, each time a new page is loaded, with the number of this page. That way, if the user wants to retrieve the second page, they can without any effort by hitting the corresponding number.
See the Pen Infinite Scroll + Pagination by SitePoint (@SitePoint) on CodePen.
Usage – HTML
<div class="article-list" id="article-list"></div>
<ul class="article-list__pagination article-list__pagination--inactive" id="article-list-pagination"></ul>
Usage – JavaScript
Please note that this code uses ES6, but you can easily convert it to ES5.
function getPageId(n) {
return 'article-page-' + n;
}
function getDocumentHeight() {
const body = document.body;
const html = document.documentElement;
return Math.max(
body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight
);
};
function getScrollTop() {
return (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
}
function getArticleImage() {
const hash = Math.floor(Math.random() * Number.MAX_SAFE_INTEGER);
const image = new Image;
image.className = 'article-list__item__image article-list__item__image--loading';
image.src = 'http://api.adorable.io/avatars/250/' + hash;
image.onload = function() {
image.classList.remove('article-list__item__image--loading');
};
return image;
}
function getArticle() {
const articleImage = getArticleImage();
const article = document.createElement('article');
article.className = 'article-list__item';
article.appendChild(articleImage);
return article;
}
function getArticlePage(page, articlesPerPage = 16) {
const pageElement = document.createElement('div');
pageElement.id = getPageId(page);
pageElement.className = 'article-list__page';
while (articlesPerPage--) {
pageElement.appendChild(getArticle());
}
return pageElement;
}
function addPaginationPage(page) {
const pageLink = document.createElement('a');
pageLink.href = '#' + getPageId(page);
pageLink.innerHTML = page;
const listItem = document.createElement('li');
listItem.className = 'article-list__pagination__item';
listItem.appendChild(pageLink);
articleListPagination.appendChild(listItem);
if (page === 2) {
articleListPagination.classList.remove('article-list__pagination--inactive');
}
}
function fetchPage(page) {
articleList.appendChild(getArticlePage(page));
}
function addPage(page) {
fetchPage(page);
addPaginationPage(page);
}
const articleList = document.getElementById('article-list');
const articleListPagination = document.getElementById('article-list-pagination');
let page = 0;
addPage(++page);
window.onscroll = function() {
if (getScrollTop() < getDocumentHeight() - window.innerHeight) return;
addPage(++page);
};
Conclusion
We’ve looked at six different examples of implementing infinite scrolling. No matter what you’re trying to build, you should be able to use one of these techniques to achieve the result you want. As always, we’d love to hear your thoughts: have you built anything cool with one of these plugins or techniques? Do you have a favorite plugin that you think should have been mentioned? Let us know in the comments!