Infinite Scroll
Everybody seems to be talking about Photon. Nobody really seemed to notice the Infinite Scroll feature added to the latest Jetpack. While it is slightly buggy, it’s pretty neat nevertheless. It’s also pretty easy to add support for in your own themes. I added it to this blog, just to see how. 🙂

So, here’s how you do it.

Step 1: Use Template Parts

Look at the HTML produced by your main Loop. The main one being the one that displays the main set of posts. This is usually in the index.php file.

Let’s say that HTML looks like this (overly simplified, of course):

<div id="content">
	<div class="post">...</div>
	<div class="post">...</div>
	<div class="post">...</div>

Each one of those posts is produced inside the loop, while the content container is outside it. Now let’s look at a simplified version of what The Loop might look like in PHP:

<?php while (have_posts()) : the_post(); ?>
        <div id="post-<?php the_ID(); ?>" <?php post_class(); ?>>
... all the post creation stuff here ...
<?php endwhile; ?>

What we need to do is to separate that “post” from the Loop itself, in a way that the Infinite Scroll code can then produce the post independently. With Template Parts, this is actually rather easy. We just cut and paste all that post-producing code, and put it in a new “content.php” file. Then we change the Loop into this:

while (have_posts()) : the_post();
	get_template_part( 'content', get_post_format() ); 

The get_template_part function will load that content.php file for us and include it there.

See a template is a file listed in the Template Hierarchy. But a template part is a file that contains only part of a template, and you can name them yourself. In this case, we named it “content”. It will become, therefore, content.php in the theme.

We also created a mini-hierarchy for ourselves while we were at it, using the Post Formats. What this means is that if I want to display, say, the “quote” format posts differently, I can copy content.php to content-quote.php, and make my changes in there. Then quotes will be displayed however I like in that new template part. And if content-quote.php doesn’t exist, then it falls back to using content.php, just like the normal fallbacks.

By separating out the Post from the surrounding loop that it’s in, then each post can be generated independently, sent over the wire via Javascript, and inserted into the page. Thus, Infinite Scroll can do the job.

Step 2: Enable Infinite Scroll

A theme can declare support for infinite scroll using add_theme_support(), like so:

add_theme_support( 'infinite-scroll', array(
	'container'    => 'content',
) );

The “container” is the ID of the element in the page that was our wrapper class. Let’s go back to that HTML again:

<div id="content">
	<div class="post">...</div>
	<div class="post">...</div>
	<div class="post">...</div>

See how the “id=content” is the big wrapper for our posts? Well, we tell the Infinite Scroll code that, it then uses it in the Javascript to know where to append the new posts to. Easy.

Step 3: Finishing touches

Simply speaking, that’s all there really is to it. But, there’s additional ways to customize it for your particular theme, to look better. Each of these is an option you can add to that add_theme_support call. Let’s go over them briefly:

Footer: You may have noticed when you enabled this and test it that you now have a sort of white footer overlay at the bottom of the page. This provides the page with a footer space that scrolls with the page, giving it a sort of finished look. Some people may like it, some not so much. We can use the footer option to adjust it.

First, using ‘footer’=>false will simply turn it off.

Alternatively, giving it the ID of some other element on the page will make it match that element’s width. For example, if you have HTML that looks like this:

<div id="page">
	<div id="content">
		<div class="post">...</div>
	<div id="sidebar">

..then using ‘footer’=>’page’ would make it match the width of the “page” element, so as to be the proper width across the screen to fit better with the page.

Type: Infinite Scroll supports two methods of loading new posts. One method is called ‘scroll’, where new posts are loaded as the user reaches the bottom of the page. When they scroll, essentially. The other is called ‘click’, which adds in a new button towards the bottom of the posts, and when you click it, it loads more posts. You can force one type or the other using the ‘type’ option.

Footer Widgets: Some themes support having widget spaces in the footer. This has become fairly commonplace after Twenty Ten did it. Well, if you’re using the scroll type, then the widgets won’t be seen for a while on some blogs, since it will just load in more posts and keep pushing that footer further down. You could set the type to click to allow the footer to actually be seen.

The ‘footer_widgets’ option lets you specify a widget space that you registered with register_sidebar(). It will check that space to see if there’s any widgets in it. If there are, then it will automatically set type to “click” so that those widgets can be seen. If not, then it will let the type stay as “scroll”. Thus, it can choose the type intelligently, depending on whether widgets exist in the footer or not.

Wrapper: If you have some complex HTML for your posts, then you can give the ‘wrapper’ option a classname to use. It will wrap the returned posts in a div with that custom classname for you. This also allows you a way to perform styling tricks on those just-loaded posts.

Render: The ‘render’ option gives you an alternative to making a content template part. You can give this a function name, and that function will be called to render the posts instead. If you’re writing a theme, I suggest using the content template part instead. It’s easier and way more flexible.

Posts per page: By default, the Infinite Scroll module makes the page show 7 posts only, then more load when you scroll down (for the ‘scroll’ type). This is smaller than most people’s settings (default of which is 10), but it doesn’t matter since the whole point is to make it load new posts when you scroll down to them. If you happen to need a different number, you can use the ‘posts_per_page’ option to change the number.

There’s also a few things you can do with CSS.

When infinite scrolling is enabled, then body_class (which you should have been using in the body tag anyway) will get the “infinite-scroll” class added to it. If the type setting is ‘scroll’ instead of ‘click’, then the class “neverending” will be there too. Also, once the user gets to the last post, the javascript code adds an “infinity-end” class to the body, meaning that you can style what happens when the user gets to the end. Jetpack’s documentation page suggests hiding the normal footer until the user actually reaches it, using CSS like this:

/* Hides navigation links and site footer when infinite scroll is active */
.infinite-scroll #navigation,
.infinite-scroll.neverending #footer {
	display: none;
/* Shows the footer again in case all posts have been loaded */
.infinity-end.neverending #footer {
	display: block;

But obviously you can use it for more than just this functionality; because it’s on the body, the classes can be used to adjust anything on the page, and make them different with the infinite scroll than without it.

You can also style the “span.infinite-loader”. This is the spinning handle thing that shows up at the bottom of posts, before the new ones load in. Honestly, the loading is pretty quick and the default style looks pretty good to me. You can adjust the style of it if you like, perhaps to make it more centered on the container.

The div#infinite-handle will be the box that shows up to load more posts, if the type is set to “click”. You can use this to reposition the box, make it wider, change the color, etc.

Finally, if you are doing anything extremely tricky with Javascript, loading in new posts may be not handled precisely well by your existing code. The official support page methods a post-load event fired on document.body that occurs when the posts are loaded. You should refer to that documentation for more info on it, if needed.


On the whole, it’s a clever module to add to Jetpack. It still has some problems with specific sorts of content (some videos display very wonky sometimes), but I’m sure they’ll have that sorted out before too long. Adding support for it in your theme might also get you thinking about Template Parts and how to use them, and that’s definitely a good thing to be doing.



  1. […] done a great tutorial on implementing one of the more glossed over parts of Jetpack 2.0: Infinite […]

  2. Cool! But one can never reach footer on homepage/archives! In case footer has some interesting things/links.. 🙂

    • If you want the footer to display, then you can set the type parameter to “click” so that the user has to click a button to load new posts.

      • footer was the key thing for me, themes have the fixed footer, but the original peek is gone, it reflected a true sense of theme author’s mentality and somehow one could gauge the guy to some extent

        add_theme_support( 'infinite-scroll', array(
        	'container'  => 'content',
        	'footer'     => 'page',
        ) );
  3. I was happy when I spotted it after upgrading Jetpack but I found out that Infinite Scroll breaks SyntaxHighlighter Evolved plugin. Not good.

  4. Thanks Otto! This info is much better than what’s on the infinite scroll site.

  5. Hi,
    i’m using wordpress and jetpack, but i don’t like infinite scroll, neither scroll mode nor click mode. i want to keep jetpack active, but i would like to use old page navigation (older posts/newer posts).

    Could you suggest me how to deactivate completely infinite scroll while maintaining jetpack active?
    thank you in advance

  6. […] to be released, support for the Jetpack Infinite Scroll module has been added. After following Otto’s guide on getting support added, I noticed that the scrolling footer that is included by default has the […]

  7. Hello, I have added the following to my functions.php

    add_theme_support( 'infinite-scroll', array(
    'container' => 'middle_single',
    'footer' => 'footer-bottom',
    ) );

    However it’s not working 🙁 Nothing new happens. It’s like the infinite scroll is deactivated, but it’s ON in the settings.

    I can’t figure out what’s wrong. If you can take a look I would post here my loop.

  8. Hello Otto, my website has a multiple column layout where one column shows the latest posts, and the other column lists the latest posts from a tag (highlights).

    So, how do I enable infinite scroll for multiple containers on the same page? I tried this (code below) among a few other options that struck my head, and so far, none worked.

    * Infinite Scroll
    add_theme_support( 'infinite-scroll', array(
    'type' => 'click',
    'container' => array( 'highlights', 'content' ),
    'footer' => false,
    ) );

    What should I be doing?


    • I’ve also tried this:

      add_theme_support( 'infinite-scroll', array(
      'type' => 'click',
      'container' => 'highlights',
      'footer' => false,
      ) );

      add_theme_support( 'infinite-scroll', array(
      'type' => 'click',
      'container' => 'content',
      'footer' => false,
      ) );

      And in this case, the latter add_theme_support overrides the first function, which means, infinite-scroll (upon click) is enabled only for the ‘content‘ container. (Just wanted to let you know what else I’ve tried.

  9. Notice you have used in your site too.
    Thanks for the tutorial and will add in my blog too.

  10. I’m going to be that guy who complains about something that is free, but it’s just that “it is slightly buggy” part….

  11. I have a question about my site. I’m trying really hard to get Bootstrap, Vanilla Masonry, and Infinite scrolling to work. I’ve updated my functions file, content.php and blog page template with all the code you wrote about. But I still can’t get my site to work. I’ll leave Infinite scroll activate so that you might see my problem.

    #containerMod is what surrounds .post, I’ve also adjusted the Functions accordingly. Can you see if there is anything that I am missing?

    My Blog Page

    Functions Code

    add_theme_support( 'infinite-scroll', array(
    'container' => 'containerMOD',
    ) );

    Blog Page Code

    'post', 'paged'=>$paged, 'showposts'=>0, 'cat'=> '8,15') );
    if (have_posts()) : while ( have_posts() ) : the_post();
    get_template_part( 'content', get_post_format() );

    content.php Code

    <li id="post-" class="post span3">

    if ( has_post_thumbnail()) {
    $full_image_url = wp_get_attachment_image_src( get_post_thumbnail_id(), 'full');
    $thumbnail_image_url = wp_get_attachment_image_src( get_post_thumbnail_id(), 'thumbnail');
    echo '';
    echo '
    else {
    ' ';
    echo ' ';

    <a href="">
    , <?php comments_popup_link( '0 ', '1 ', '% ', 'comments-link', 'Comments are off for this post');?> <?php edit_post_link(__(''), ''); ?>

  12. Otto great article thanks!

    I’m getting the footer to show up but it’s not actually loading new posts, plus the page navi is still there?

  13. I just don’t get it. Added the code to functions.php activated inifnite scroll module. And after that I am clueless. 😀
    Any one can help ?

  14. I followed everything you wrote, and I understood everything but somehow I cannot get it to work. I am on WordPress 3.6.

  15. […] If your theme doesn’t support Infinite Scroll, you can follow this excellent tutorial to make the necessary changes to your template files: Jetpack and the Infinite Scroll. […]

  16. I use click-button for loading further content. Is there an easy way to change the text of the button, maybe in the function.php ?

  17. How and where can I find the code to style the “Older Posts” button?

    I noticed you mentioned the div#infinite-handle but I can’t seem to find it.

    Please Help!

  18. Still searching the code -Hope i too find the solution from this writeup,Will get back to you whatever the outcome

  19. Hello,

    How can I use scroll with query_posts on template page?

    $paged = get_query_var(‘paged’) ? get_query_var(‘paged’) : 1;
    $args = array(
    ‘post_type’ => ‘testimonial’,
    ‘posts_per_page’ => 2,
    ‘paged’ => $paged
    query_posts( $args );


  20. […] may want to check out this solution by developer Samuel Wood, aka Otto, which explains how to separate your posts from the WordPress loop so you can enable […]

  21. […] kommt euch dieser Beitrag von Samuel „Otto“ Wood zur Hilfe. Jedoch solltet ihr aufpassen, denn diese Lösungsvariante ist sehr Code-lastig. Wer sich […]

  22. I have followed the steps of this guide (and many others, starting with the documentation provided by jetpack of course) I have made sure that infinite scroll is enabled in both jetpack settings & in Settings->Reading, yet nothing happens at all, nothing about my site has changed. I am getting a bit desperate here.

    • Okay, I checked my console on the browser to make sure there were no errors being thrown, and there were not. I assumed this would not be an issue, but it actually turns out that a plugin I have conflicts with infinite scroll. I had to disable “NextGEN Gallery by Photocrati”, which is a bit of a bummer, but hey, I would rather have infinite scrolling than a plugin I rarely use.

  23. […] all of the posts. Can anyone help me out with picking the right selectors? I was going off of this article but no results 🙁 Using this code in […]

  24. […] have carefully followed the instructions at OttoPress, and read all the documentation at I feel like I understand what should work, but for […]

  25. Fantastic. Very well explained, but unfortunately it didn’t work for me. I posted about it on WordPress SE. Any ideas as to why? ( ) Thanks so much.

  26. […] have carefully followed the instructions at OttoPress, and read all the documentation at I feel like I understand what should work, but for […]

  27. […] much I followed the instructions, the plugin would not fire. In 2012, WordPress contributor, Otto, wrote a pretty simple article on how to get infinite scroll to work with a custom theme. What it did not have was the ‘ Why doesn’t […]

  28. Is it also possible to use this without installing Jetpack? It has a lot of items in it i’m not going to use, but I want to create a infinite scroll archive page in my _s-template (underscores).

    Or does someone know a good alternative that is easy to implement for a newbie (at this area)?

  29. […] may want to check out this solution by developer Samuel Wood, aka Otto, which explains how to separate your posts from the WordPress loop so you can enable […]

Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Need to post PHP code? Wrap it in [php] and [/php] tags.