Extras

Module loaders

Webpack & Browserify

Install Infinite Scroll with npm or Yarn.

# npm
npm install infinite-scroll
# Yarn
yarn add infinite-scroll

You can then require('infinite-scroll').

// main.js
const InfiniteScroll = require('infinite-scroll');

let infScroll = new InfiniteScroll( '.container', {
  // options...
});

Compile your JS with Webpack or Browserify.

# Webpack
webpack main.js bundle.js
# Browserify
browserify main.js -o bundle.js

To use Infinite Scroll as a jQuery plugin, you need to call jQuery Bridget.

# npm
npm install jquery-bridget
# Yarn
yarn add jquery-bridget
// main.js
const $ = require('jquery');
const jQueryBridget = require('jquery-bridget');
const InfiniteScroll = require('infinite-scroll');

// make Infinite Scroll a jQuery plugin
jQueryBridget( 'infiniteScroll', InfiniteScroll, $ );
// now you can use $().infiniteScroll()
$('.container').infiniteScroll({...});

When installed with a package manager, Infinite Scroll does not include imagesLoaded, which is required to use outlayer. You will need to install and require imagesLoaded separately.

# npm
npm install imagesloaded
# Yarn
yarn add imagesloaded
// main.js
const Masonry = require('masonry-layout');
const InfiniteScroll = require('infinite-scroll');
const imagesLoaded = require('imagesloaded');

// init Masonry
let msnry = new Masonry( '.container', {...});

// make imagesLoaded available for InfiniteScroll
InfiniteScroll.imagesLoaded = imagesLoaded;

// now you can use outlayer option
let infScroll = new InfiniteScroll( '.container', {
  // options...
  outlayer: msnry,
});

Loading JSON

Here is one example of how to use Infinite Scroll to load JSON data and append content. We'll use the Unsplash API to load pages of photos.

let $container = $('.container').infiniteScroll({
  path: function() {
    return 'https://api.unsplash.com/photos?client_id=...&page=' + this.pageIndex;
  },
  // load page as JSON
  responseBody: 'json',
  // disable history
  history: false,
});

$container.on( 'load.infiniteScroll', function( event, body ) {
  // body is JSON, put that data into template
  let itemsHTML = template.compile( body );
  // convert to jQuery object
  let $items = $( itemsHTML );
  // append items
  $container.append( $items );
});

Edit this demo or vanilla JS demo on CodePen

See additional demos:

Button behaviors

Click button to start loading on scroll

let $container = $('.container').infiniteScroll({
  // options...
  // disable loading on scroll
  loadOnScroll: false,
});

let $viewMoreButton = $('.view-more-button');
$viewMoreButton.on( 'click', function() {
  // load next page
  $container.infiniteScroll('loadNextPage');
  // enable loading on scroll
  $container.infiniteScroll( 'option', {
    loadOnScroll: true,
  });
  // hide button
  $viewMoreButton.hide();
});
1a
1b
1c
1d

End of content

No more pages to load

Edit this demo or vanilla JS demo on CodePen

Scroll 2 pages, then load with button

let $container = $('.container').infiniteScroll({
  // options...
  // enable button
  button: '.view-more-button',
});

let $viewMoreButton = $('.view-more-button');

// get Infinite Scroll instance
let infScroll = $container.data('infiniteScroll');

$container.on( 'load.infiniteScroll', onPageLoad );

function onPageLoad() {
  if ( infScroll.loadCount == 1 ) {
    // after 2nd page loaded
    // disable loading on scroll
    $container.infiniteScroll( 'option', {
      loadOnScroll: false,
    });
    // show button
    $viewMoreButton.show();
    // remove event listener
    $container.off( 'load.infiniteScroll', onPageLoad );
  }
}
1a
1b
1c
1d

End of content

No more pages to load

Edit this demo or vanilla JS demo on CodePen

Loading URLs from loaded pages

You can use Infinite Scroll to load the next article page by updating the next URL from the loaded page. For example, the current URL is /news/alpha, and its next link /news/beta; and when you load /news/beta, its next link is /news/gamma.

To do so, you can use a nextURL variable and update it on load, then set path to a function to return nextURL.

let nextURL;

function updateNextURL( doc ) {
  nextURL = $( doc ).find('.pagination__next').attr('href');
}
// get initial nextURL
updateNextURL( document );

// init Infinite Scroll
let $container = $('.container').infiniteScroll({
  // use function to set custom URLs
  path: function() {
    return nextURL;
  },
});

// update nextURL on page load
$container.on( 'load.infiniteScroll', function( event, body ) {
  updateNextURL( body );
});

Loading animations

Feel free to use these loading animations within .infinite-scroll-request status element.

<div class="loader-ellips">
  <span class="loader-ellips__dot"></span>
  <span class="loader-ellips__dot"></span>
  <span class="loader-ellips__dot"></span>
  <span class="loader-ellips__dot"></span>
</div>
.loader-ellips {
  font-size: 20px; /* change size here */
  position: relative;
  width: 4em;
  height: 1em;
  margin: 10px auto;
}

.loader-ellips__dot {
  display: block;
  width: 1em;
  height: 1em;
  border-radius: 0.5em;
  background: #555; /* change color here */
  position: absolute;
  animation-duration: 0.5s;
  animation-timing-function: ease;
  animation-iteration-count: infinite;
}

.loader-ellips__dot:nth-child(1),
.loader-ellips__dot:nth-child(2) {
  left: 0;
}
.loader-ellips__dot:nth-child(3) { left: 1.5em; }
.loader-ellips__dot:nth-child(4) { left: 3em; }

@keyframes reveal {
  from { transform: scale(0.001); }
  to { transform: scale(1); }
}

@keyframes slide {
  to { transform: translateX(1.5em) }
}

.loader-ellips__dot:nth-child(1) {
  animation-name: reveal;
}

.loader-ellips__dot:nth-child(2),
.loader-ellips__dot:nth-child(3) {
  animation-name: slide;
}

.loader-ellips__dot:nth-child(4) {
  animation-name: reveal;
  animation-direction: reverse;
}
<div class="loader-wheel">
  <i><i><i><i><i><i><i><i><i><i><i><i>
  </i></i></i></i></i></i></i></i></i></i></i></i>
</div>
.loader-wheel {
  font-size: 64px; /* change size here */
  position: relative;
  height: 1em;
  width: 1em;
  padding-left: 0.45em;
  overflow: hidden;
  margin: 0 auto;
  animation: loader-wheel-rotate 0.5s steps(12) infinite;
}

.loader-wheel i {
  display: block;
  position: absolute;
  height: 0.3em;
  width: 0.1em;
  border-radius: 0.05em;
  background: #333; /* change color here */
  opacity: 0.8;
  transform: rotate(-30deg);
  transform-origin: center 0.5em;
}

@keyframes loader-wheel-rotate {
  from { transform: rotate(0deg); }
  to { transform: rotate(360deg); }
}

Google Analytics

Use Infinite Scroll events to track pageviews with Google Analytics.

With history option enabled, use the history event.

$container.on( 'history.infiniteScroll', function() {
  ga( 'set', 'page', location.pathname );
  ga( 'send', 'pageview' );
});

With history option disabled, use the append or load event.

// link used to get absolute path, beginning with /
let link = document.createElement('a');

$container.on( 'append.infiniteScroll', function( event, response, path ) {
  link.href = path;
  ga( 'set', 'page', link.pathname );
  ga( 'send', 'pageview' );
});

Browser support

Infinite Scroll v4 supports Chrome 60+, Edge 79+, Firefox 55+, Safari 11+.

For IE10 and Android 4 support, try Infinite Scroll v3.

Upgrading from v3

Infinite Scroll v4 is mostly backwards compatible with v3.

The one breaking change is that Infinite Scroll v4 removed responseType option in favor of responseBody. This change effects loading JSON in particular. To load JSON with Infinite Scroll v4, set responseBody: 'json' in your options. Then the body argument in the load event will be JSON.

// Infinite Scroll v3
let $container = $('.container').infiniteScroll({
  path: function() {
    return 'https://api.unsplash.com/photos?client_id=...&page=' + this.pageIndex;
  },
  // load page as text
  responseType: 'text',
  // disable history
  history: false,
});

$container.on( 'load.infiniteScroll', function( event, response ) {
  // parse response text into JSON data
  var data = JSON.parse( response );
  // put that data into template
  var itemsHTML = template.compile( data );
  // convert to jQuery object
  var $items = $( itemsHTML );
  // append items
  $container.infiniteScroll( 'appendItems', $items );
});
// Infinite Scroll v4
let $container = $('.container').infiniteScroll({
  path: function() {
    return 'https://api.unsplash.com/photos?client_id=...&page=' + this.pageIndex;
  },
  // load page as json
  responseBody: 'json',
  // disable history
  history: false,
});

$container.on( 'load.infiniteScroll', function( event, body ) {
  // body is JSON data
  var itemsHTML = template.compile( body );
  // convert to jQuery object
  var $items = $( itemsHTML );
  // append items
  $container.infiniteScroll( 'appendItems', $items );
});

New features

  • Uses fetch API to make requests
  • loadNextPage returns a Promise
  • Set headers and fetch options with fetchOptions
  • 10% smaller filesize
  • Internet Explorer support dropped

Issues

Reduced test cases

Creating a reduced test case is the best way to debug problems and report issues. Read CSS Tricks on why they’re so great.

Create a reduced test case for Infinite Scroll by forking any one of the CodePen demos from these docs.

  • A reduced test case clearly demonstrates the bug or issue.
  • It contains the bare minimum HTML, CSS, and JavaScript required to demonstrate the bug.
  • A link to your production site is not a reduced test case.

Creating a reduced test case is the best way to get your issue addressed. They help you point out the problem. They help us debug the problem. They help others understand the problem.

Submitting issues

Report issues on GitHub. Make sure to include a reduced test case. Without a reduced test case, your issue may be closed.

Feature requests

Help us select new features by looking over requested features on the GitHub issue tracker and adding your +1 reaction to features you’d like to see added.