Archive for November 2012

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>
</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 ...
        </div>
<?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:

<?php 
while (have_posts()) : the_post();
	get_template_part( 'content', get_post_format() ); 
endwhile; 
?>

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>
</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>
	<div id="sidebar">
		<div>...</div>
	</div>
</div>

..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.

Summary

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.

Shortlink: