Affari

AJAX lazy load with WordPress Pagination

March 13, 2015
James Herriott

The Goal

You’ve probably seen a lazy load being used on websites or in mobile apps like Instagram or Twitter. The basic concept is, when a user initially loads the page they are only served enough posts to fill their screen. Then, as the user scrolls down and their window approaches the bottom of the document a new set of posts are dynamically loaded into the page. This repeats over and over until all the posts are fully loaded. This can be accomplished using WordPress pagination and some basic jQuery. To see a working example of AJAX lazy load with WordPress Pagination click here.

The Code

Start with a wrapping div:

<div id=”lazyload”>

</div>

Inside this div modify the query:

<?php
  $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
  $query_args = array(
    'post_type' => 'post',
    'posts_per_page' => 5,
    'paged' => $paged
  );
  if (have_posts()) {
?>

<?php
  }
?>

Within your ‘if’ statement put a div that will contain each page’s elements and has an unique page-specific id:

<div class="page" id="p<?php echo $paged; ?>">

</div>

Next, drop in your loop for each page’s posts:

<?php while (have_posts()) { the_post(); ?>
  <article>
    <header class="entryheader">
      <h2 class="entrytitle"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
    </header>
    <div class="entrycontent">
      <?php the_excerpt(); ?>
    </div>
  </article>
<?php } ?>

Now add a spinner to the bottom of the page. Keep it outside the “lazy load” div at the bottom of your document:

<div id="spinner">
  <img src="loading.gif">
</div>

At this point you have a page template that shows 5 posts on each page. Add /?p=2 to the url to make sure the pagination is working. Next we’ll implement the script that will use the jQuery load() function to pull posts in via the WordPress pagination url. First we’ll add a script tag with a jQuery function containing two variables:

<script>
  jQuery(function(){
    var page = 2;
    var loadmore = 'on';
  });
</script>

We’ll use the first variable ‘page’ to determine what page should be loaded next. The second variable ‘loadmore’ will prevent multiple .load() functions from happening at the same time. Now within the jQuery function add an .on(‘scroll resize’) trigger:

jQuery(document).on('scroll resize', function() {

});

Within this function we’ll add a condition to check if the bottom of the last loaded page is nearing the bottom of the browser’s window and another condition to check if ‘loadmore’ is set to ‘on’.

if (jQuery(window).scrollTop() + jQuery(window).height() + 60 > jQuery(document).height()) {
  if (loadmore == 'on') {
  }
}

Now if these two conditions are met we want to load the next page of posts into our #lazyload div. The first thing we’ll do is set ‘loadmore’ to ‘off’ so that we only load one page at a time. Then set the #spinner div to be visible to make the user aware that another set of posts are being loaded in.

loadmore = 'off';
jQuery('#spinner').css('visibility', 'visible');

Now we can use the jQuery .load() function to pull our content into the page. We don’t want to replace the content entirely we want to append the content at the end of our #loadmore div. Here’s the code:

jQuery('#lazyload').append(jQuery('<div class="page" id="p' + page + '">').load('YOURURLHERE/?paged=' + page + ' .page > *', function() {

}));

When working with AJAX lazy load with WordPress, be sure to replace YOURURLHERE with the url of the page you’re working on. You’ll notice that we’re appending a div that contains a unique id specific to the page we’re pulling in. This id is used to detect when the ‘page’ div is nearing the bottom of the page for the function to repeat. Within this function put these three events that will be triggered once the .load() function has completed:

page++;
loadmore = 'on';
jQuery('#spinner').css('visibility', 'hidden');

As you can see, we’ve increased the ‘page’ variable by 1 to load the next page. Then we set the ‘loadmore’ variable to ‘on’ and set the #spinner to be hidden. The final thing we should do is detect if the .load() function doesn’t return any data. That way once the final page has loaded the user won’t continue to see a spinner at the bottom as they scroll down. This function should sit within the root of your jQuery function and will look like this:

jQuery( document ).ajaxComplete(function( event, xhr, options ) {
  if (xhr.responseText.indexOf('class="page"') == -1) {
loadmore = 'off';
  }
});

Here is what your complete code should look like:

<div id="lazyload" class="grid_12">
<?php
  $paged = ( get_query_var('paged') ) ? get_query_var('paged') : 1;
  $query_args = array(
    'post_type' => 'post',
    'posts_per_page' => 5,
    'paged' => $paged
  );
?>
  <?php if (have_posts()) { ?>
    <div class="page" id="p<?php echo $paged; ?>">
    <?php while (have_posts()) { the_post(); ?>
      <article id="post-<?php the_ID(); ?>" <?php post_class('entry') ?>>
        <header class="entryheader">
          <h2 class="entrytitle"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
        </header>
        <div class="entrycontent">
          <?php the_excerpt(); ?>
        </div>
      </article>
    <?php } ?>
    </div>
  <?php } ?>
</div>
<div id="spinner">
  <img src="loading.gif">
</div>
<script>
  jQuery(function(){
    var page = 2;
    var loadmore = 'on';
    jQuery(document).on('scroll resize', function() {
      if (jQuery(window).scrollTop() + jQuery(window).height() + 60 > jQuery(document).height()) {
        if (loadmore == 'on') {
          loadmore = 'off';
          jQuery('#spinner').css('visibility', 'visible');
          jQuery('#lazyload').append(jQuery('<div class="page" id="p' + page + '">').load('/?paged=' + page + ' .page > *', function() {
            page++;
            loadmore = 'on';
            jQuery('#spinner').css('visibility', 'hidden');
          }));
        }
      }
    });
    jQuery( document ).ajaxComplete(function( event, xhr, options ) {
      if (xhr.responseText.indexOf('class="page"') == -1) {
        loadmore = 'off';
      }
    });
  });
</script>

Thanks for reading this post about AJAX lazy load with WordPress Pagination, we hope it helped you! Don't forget to follow us on social media to stay up to date on all our development blog posts! Twitter, Facebook and Instagram.


James showed up at Affari with several years of experience writing and managing large scale cloud applications. Even while he hibernates through long Montana winters, he wants to make sure your platform succeeds out in the wild, no matter what the size.

Get more insights to your inbox

Ideas are what make us
great, let’s talk about yours

(202) 643-9322 | hello@affari.co

© 2017 Affari. Made across the USA with love.