Conditional and custom next/previous post links in WordPress

Many blogs have links to the next and previous posts at the beginning or end of each post. The default theme in WordPress 3.0, TwentyTen, has those links too. But what happens when you’re viewing either the latest post or the very first post of a blog?

In TwentyTen, no previous link will be created on the first post, and no next link will be output on the latest post. This makes sense since there obviously is nothing “previous” or “next” to link to. However, there is some unnecessary markup that will always be output, and here are a couple of ways to get rid of it.

The code in TwentyTen is in the single.php template file and looks like this:

<div id="nav-below" class="navigation">
	<div class="nav-previous"><?php previous_post_link( '%link', '<span class="meta-nav">' . _x( '←', 'Previous post link', 'twentyten' ) . '</span> %title' ); ?></div>
	<div class="nav-next"><?php next_post_link( '%link', '%title <span class="meta-nav">' . _x( '→', 'Next post link', 'twentyten' ) . '</span>' ); ?></div>

This will leave the containing div element for each link in the markup even when there is no previous or next link. I don’t like unused HTML lying around, so I wanted to get rid of it. Besides, I tend to put these links in an unordered list, and having an empty list item is arguably worse accessibility-wise than having an empty div.

Here is what you can use instead of the default code:

<?php if (get_adjacent_post(false, '', true)): // if there are older posts ?>
	<li class="prev">Previous post: <?php previous_post_link('%link'); ?></li>
<?php endif; ?>
<?php if (get_adjacent_post(false, '', false)): // if there are newer posts ?>
	<li class="next">Next post: <?php next_post_link('%link'); ?></li>
<?php endif; ?>

The get_adjacent_post function takes three parameters: $in_same_cat, $excluded_categories, and $previous. It’s the $previous parameter we’re interested in here. When this parameter is set to true, which is the default, the function returns the previous post, and when it’s set to false, well, the next post is returned. If no post is found, an empty string is returned.

By simply checking if get_adjacent_post returned anything before writing the elements containing the links to the page you can avoid creating unused markup. I like that.

I still wasn’t happy though, since you can’t do enough to customise the output of the previous_post_link and next_post_link functions. To get complete control of the output you can use this:

$previous_post = get_adjacent_post(false, '', true);
$next_post = get_adjacent_post(false, '', false);
<?php if ($previous_post): // if there are older articles ?>
	<li class="prev">Previous post: <a href="<?php echo make_href_root_relative(get_permalink($previous_post)); ?>"><?php echo get_the_title($previous_post); ?></a></li>
<?php endif; ?>
<?php if ($next_post): // if there are newer articles ?>
	<li class="next">Next post: <a href="<?php echo make_href_root_relative(get_permalink($next_post)); ?>"><?php echo get_the_title($next_post); ?></a></li>
<?php endif; ?>

By manually getting the href and title of the posts you can customise the markup exactly the way you want it. Please note that the make_href_root_relative function is not a WordPress function but a custom function I describe in How to make WordPress URLs root relative.

Posted on December 10, 2010 in WordPress