WordPress’ next_post_link() and previous_post_link() functions are used to navigate between posts in single post (permalink) view. They work great…until you come to the very first or the very last post.
When viewing the latest post, next_post_link() displays nothing; when viewing the earliest post, previous_post_link() displays nothing. This can result in some less than friendly navigation.
In this post, I’ll show you how to use a built-in WordPress function and PHP conditionals to improve your WordPress page navigation.
The problem
Here is an example of next_post_link() and previous_post_link() at work on our blog’s old theme:

When viewing a post that is neither the newest nor the oldest, the post navigation links display as expected.
The trouble with these functions comes when you get to the first or last post. In the case of the first, you’ll have something like this:

When viewing the oldest post, the "previous post" link disappears, leaving an ugly hole.
And when viewing the last post, you’ll have something like this:

Similarly, when viewing the newest post, the "next post" link disappears.
To the rescue: get_adjacent_post
We’re going to use the obscure WordPress function get_adjacent_post() to check if… (shockingly) …there is an adjacent post. If there isn’t, we output whatever HTML markup we like to take the place of the gaping hole we’re trying to fill. If there is an adjacent post, we output it as normal.
The function retrieves a link to the adjacent post (either next or previous) and takes the following form…
get_adjacent_post([bool $in_same_cat, string $excluded_categories, bool $previous])
…and has these parameters:
- $in_same_cat : Whether the link should be in the same category
- $excluded_categories : A comma-separated list of excluded category IDs
- $previous : Whether to retrieve the previous post
The solution, with sample markup
The code block below contains the markup you should add to your single.php template file. Place it where you’d like your navigation to appear, then adjust the parameters and output to suit your needs.
<span id="prev"> <?php previous_post_link('%link', '« Previous'); ?> <?php if(!get_adjacent_post(false, '', true)) { echo '<span>«Previous</span>'; } // if there are no older articles ?> </span> <span id="next"> <?php next_post_link('%link', 'Next »'); ?> <?php if(!get_adjacent_post(false, '', false)) { echo '<span>Next »</span>'; } // if there are no newer articles ?> </span>
I then added this line to my CSS file:
#prev span, #next span { color:#ccc; } /* lighter than the normal anchor text */
And here is the final result:

The final result, showing user-friendly language at both ends.
In the example above, I grayed out the inactive links. If you have more room, you might get creative by replacing the text with something like “Sorry, there aren’t any newer posts!”

34 Comments
I don’t know If I said it already but …Excellent site, keep up the good work. I read a lot of blogs on a daily basis and for the most part, people lack substance but, I just wanted to make a quick comment to say I’m glad I found your blog. Thanks,
A definite great read..Jim Bean
Thanks for the comment Jim!
Hi, thanks for this tutorial. I was wondering if you could tell me how to change the navigation system of a wordpress blog? Right now, on my home page- there’s a link which says “Previous Comic”, which leads to “/page/2″. Is it possible to make that link to a permalink of the previous post (comic), instead of page 2?
I’ve been browsing the net and can’t seem to find out how to do this..
Thanks for your time!
Hi Chibi,
The WordPress tags used in this tutorial only work on single post (permalink) pages, i.e. those pages that only show one post at a time.
As such, there’s no way to do what you’re asking from the homepage. WordPress has a couple of functions that let you skip to older posts and newer posts; you can read about those here and here.
Ah..really? It seems possible in wordpress hosted webcomics, e.g http://www.wetherobots.com/ though. Any ideas?
Chibi,
After doing a bit of searching I found a solution that should do the trick. Place the following bit of code in The Loop where you want the link to appear:
This will tell WP to treat the current page as a single page, even if it’s your home page. I hope that helps.
Thanks so much for taking the time to reply
I tried putting that code in and nothing seems to happen. I’m probably putting it in the wrong place.. it just seems to display the text.
Can you be any more specific?
Thanks!
No problem
I tested this in my index.php file and it works for me:
< ?php query_posts('showposts=1'); if(have_posts()) : while(have_posts()) : the_post(); $wp_query->is_single = true; previous_post_link(); // display your most recent post here endwhile; endif; ?>The query_posts bit will show only your most recent post on the homepage, which is what I assume you’d like to do. Then you step into The Loop, and the next bit of code tells WP to treat your index.php like a single post page, so the previous_post_link function works like you want it to. Place this wherever you’d like the link to your previous comic to appear.
Below that, you can use WP functions like the_title and the_content to display your most recent post however you like.
Then we exit The Loop.
Let me know if you have trouble and I can take a closer look at what you’re doing.
Great! It works!
Thank you so much for helping me out with this. You’re a real life saver!
Great – glad I could help!
This method nice but it doesn’t working for me. This is my custom page template for showing post with images.
When i use
get_adjacent_post()function then everytime showing disabled prev/next elements (can you look this video?).So what i must do for use your method?
Hi Fatihturan,
It looks like there are just a couple of small differences between the code I provided above and the code in your custom page template. I’m looking at lines 44-47 of your template.
You’re using the functions previous_posts_link and next_posts_link (with an “s”), but you should be using previous_post_link and next_post_link (without the “s”).
Also, on line 47 of your template, make sure it reads like this:
< ?php if(!get_adjacent_post(false, '', false)) { echo '< a href="javascript:;" rel="nofollow">Sonraki »'; } ?>You have (false, ”, true) instead of (false, ”, false).
But if i use
previous_post_link(without s) it’s doesn’t showing next/prev links.I think
previous_post_link(without s) functions is using on single.php template.If you look my template you will see what i’m using (custom page template).
Ahhh, I hadn’t noticed that you were using a custom template.
The reason the prev/next links are disabled is because there are no other posts to show; you’ve limited your query to 2 posts, so WordPress is only going to pull those 2 posts and show them; there are no other posts to link to.
Why not use single.php? You’ll have to reinvent the wheel if all you’re trying to do is get a custom template to function like single post view.
If you have other posts that need to use single.php, and you also want to use single view to show some photos, then you can add some conditionals at the top of your single.php to check what page you’re on, e.g.:
< ?php if(is_page('photos')) : ?> // do your thing < ?php else : ?> // standard single post view < ?php endif; ?>I was going to use the empty() function to check if next_post_link and previous_post_link returned anything, then act accordingly, but your use of get_adjacent_post is more elegant. Thanks for sharing.
–JP
Thanks! That get_adjacent_post function is exactly what I was looking for. Never heard of it before, but it did the trick. Put it in some nested if statements and got the empty nav spans conditionally removed from all my pages.
Not sure how to post code or I’d share.
Excellent article, I’ve been looking for a solution for this for too long! Thanks for posting.
Hi Ryan,
I’ve been looking for this solution.. and thanks for making it look easier. Can it be possible to add an hover effect to those next/previous links.. so, they reveal the post title when hovered??
thanks again/
Hey Venkat,
I’m glad you enjoyed the tutorial! If I understand you correctly, you’d like the links to say “Previous” and “Next” normally, but on hover display the title of the previous or next post. If that’s the case, you may be able to do this with straight CSS and some tweaks to your WordPress template.
Try this:
1. In your WP template, store the title of the blog post in a PHP variable (for example,
$title = get_the_title('...');)2. Echo the title of your previous/next post into a
< div>or other container, and hide it with some CSS3. On hover of the “Previous/Next” links, use CSS to hide the “Previous/Next” and then show the post titles.
Man you are awesome.. thanks a load!
Hi ryan.. i’ve tried to use get_the_title() variable… but.. couldn’t figure it well..
Mind a code snippet when possible.. please!
Hey Venkat,
Turns out you don’t need to use get_the_title(). Sorry
Replace the code from the tutorial with this (be sure to remove the spaces!):
< span id="prev"> < div>< ?php previous_post_link('%link'); ?> < div>< ?php previous_post_link('%link', __('« Previous', 'elegante')); ?> < ?php if(!get_adjacent_post(false, '', true)) { _e('« Previous', 'elegante'); } ?> < /span> < span id="next"> < div>< ?php next_post_link('%link'); ?> < div>< ?php next_post_link('%link', __('Next »', 'elegante')); ?> < ?php if(!get_adjacent_post(false, '', false)) { _e('Next »', 'elegante'); } ?> < /span>Then, in your theme’s CSS file, add the following rules:
#prev div, #next div { display:none; } #prev:hover div, #next:hover div { display:inline; } #prev div + div, #next div + div { display:inline; } #prev:hover div + div, #next:hover div + div { display:none; }I’ve only tested in Firefox, so let me know if you have any trouble!
thats cool ryan.
Thanks for ya help. It works
Hello.
Where and how do i add the $in_same_cat into your simple example?
Cannot seem to get it to work..
Cheers
Hey there Jez,
Take a look above, below the heading that says “The solution, with sample markup.” The get_adjacent_posts() function takes the $in_same_cat as the first parameter. Set it to “true” if you only want to retrieve posts that are in the same category as the one you’re viewing; “false” if you want to retrieve posts in any category.
What exactly is not working for you? Maybe I can be of more help if you provide some more details.
Cheers Ryan, so it looks like this…
<?php if(!get_adjacent_post(true, '', true)) { echo '«Previous'; } // if there are no older articles ?> <?php if(!get_adjacent_post(true, '', false)) { echo 'Next »'; } // if there are no newer articles ?>Because i tried that and it just scrolls through all the posts, i am using this in a news category and want it to work just with say cat id 9..
Hey Jez,
I was having trouble with email notifications so I apologize for the delayed response. If you take a look at the functions above you’ll see that they take a comma separated list of excluded categories as the second parameter. So to exclude categories 4 and 6 you would put:
< ?php if(!get_adjacent_post(false, '4,6', true)) { echo '«Previous'; } ?>Hi there, thanx for great solution. But can you explain how to add in { echo ‘Next »’; } instead of word: Next.?
Hi 2K, I’m not sure what your question is; would you mind clarifying?
How would you make the “previous” or “next” be an image button instead of text?
Hey Matt,
All you need to do is replace this piece:
with something like:
You can even replace the img HTML code with a variable:
Ryan, when using image like this, instead of text, is it possible to get alt=”previous post title name” instead alt=”previous”?
Hey 2k,
I’m not really sure — you might be able to use get_the_title(), but I don’t know which post ID you’d pass in.
thanks for the tip. just what is was looking for
Post a Comment