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:
And when viewing the last post, you’ll have something like this:
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:
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!”



52 comments
JimmyBean
October 1, 2009I 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
Ryan Burney
October 2, 2009Thanks for the comment Jim!
chibi
October 19, 2009Hi, 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!
Ryan Burney
October 19, 2009Hi 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.
chibi
October 19, 2009Ah..really? It seems possible in wordpress hosted webcomics, e.g http://www.wetherobots.com/ though. Any ideas?
Ryan Burney
October 19, 2009Chibi,
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.
chibi
October 20, 2009Thanks 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!
Ryan Burney
October 20, 2009No 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.
chibi
October 20, 2009Great! It works!
Thank you so much for helping me out with this. You’re a real life saver!
Ryan Burney
October 20, 2009Great – glad I could help!
fatihturan
November 30, 2009This 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?
Ryan Burney
November 30, 2009Hi 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).
fatihturan
November 30, 2009But 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).
Ryan Burney
December 4, 2009Ahhh, 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; ?>JP
December 11, 2009I 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
Missingtoof
January 30, 2010Thanks! 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.
Si Davies
February 6, 2010Excellent article, I’ve been looking for a solution for this for too long! Thanks for posting.
venkat
April 6, 2010Hi 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/
Ryan
April 7, 2010Hey 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.
venkat
April 7, 2010Man you are awesome.. thanks a load!
venkat
April 8, 2010Hi ryan.. i’ve tried to use get_the_title() variable… but.. couldn’t figure it well..
Mind a code snippet when possible.. please!
Ryan
April 8, 2010Hey 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!
venkat
April 9, 2010thats cool ryan.
Thanks for ya help. It works
Jez Thompson
June 18, 2010Hello.
Where and how do i add the $in_same_cat into your simple example?
Cannot seem to get it to work..
Cheers
Ryan
June 18, 2010Hey 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.
Jez Thompson
June 18, 2010Cheers 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..
Ryan
July 6, 2010Hey 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'; } ?>2k
July 6, 2010Hi there, thanx for great solution. But can you explain how to add in { echo ‘Next »’; } instead of word: Next.?
Ryan
July 6, 2010Hi 2K, I’m not sure what your question is; would you mind clarifying?
2k
July 30, 2010Ryan, when using image like this, instead of text, is it possible to get alt=”previous post title name” instead alt=”previous”?
Ryan
August 2, 2010Hey 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.
Matt
July 29, 2010How would you make the “previous” or “next” be an image button instead of text?
Ryan
July 29, 2010Hey Matt,
All you need to do is replace this piece:
with something like:
You can even replace the img HTML code with a variable:
tim
August 18, 2010thanks for the tip. just what is was looking for
DNicholls
January 6, 2011I have a wordpress blog that is fed into my website. I want only 1 post per page. Can I use the next and previous buttons to do this? I took your first code and put it in and it works great but it will take me to the outside wordpress blog and not keep it in my website template. Help!!
Thanks!
Ryan Burney
January 10, 2011Hi DNicholls,
I don’t fully understand your setup. Can you provide a link to your site so I can have a look?
BJ
January 21, 2011Wow thanks,
I’ve been searching for this for ever.. I hate the WP-navi plugin with all the listed page numbers.
Also the option to navigate foward and backward in the same category is so important!
Thanks..
Ryan Burney
January 21, 2011BJ,
Great! I always love to hear when these tutorials help people out.
BJ
January 29, 2011Hi Ryan,
Is this also going to work on the category-page (template) ?
I found the same above and bottom navigation inside the loop.
And i also wish to show off both (NEXT and PREV) buttons when there is a page 2.
This was the code i placed on my sidebar to navigate between posts on the same category. (works 100%)
<?php previous_post_link('%link', 'Vorige', true, ''); ?><?php if(!get_adjacent_post(false, '' ,true)) { echo 'Vorige'; } // if there are no older articles ?> <?php next_post_link('%link', 'Volgende', true, ''); ?><?php if(!get_adjacent_post(true, '' ,false)) { echo 'Volgende'; } // if there are no newer articles ?>But now i want to do the same ‘echo thing’ on the category-page with this basic ‘Twentyten’ code. Only when there is more than one page to navigate else the navigation will not show up entirely i’m fine with that setup..
I try to put the ‘echo’ line behind it but that doesn’t work..
Meghan
May 15, 2011I am hoping you can tell me how to use this method or a similar method to have the links always show in my custom template.
They are totally screwy right now and not working correctly.
<?php previous_posts_link(''); ?> <?php if(!get_adjacent_post(false, '', false)) { echo ''; } // if there are no older articles ?> <?php next_posts_link(' <?php if(!get_adjacent_post(false, '', false)) { echo ''; } // if there are no newer articles ?>Ryan
May 23, 2011Hi Meghan,
Sorry for taking so long to get back to you — I was on vacation last week
If you look closely at your code, you’ll notice that the
next_posts_link()function is missing some things. What you have:< ?php next_posts_link('Should be:
< ?php next_post_link('%link', 'Next »'); ?>That should do it -- let me know if you need anything else!
Jefferson
July 25, 2011I’m using the category parameter, so it just comes up blank when there are no more posts in the category. Thanks to your surfacing the “obscure” function, I can now link back to the home page. So… (in Suffusion theme):
<td class='previous'> <?php previous_post_link('%link', '%title', TRUE) ?> <?php if(!get_adjacent_post(TRUE, '', TRUE)) { echo '<a href="/">Home</a>'; } ?> </td> <td class='next'> <?php next_post_link('%link', '%title', TRUE) ?> <?php if(!get_adjacent_post(TRUE, '', FALSE)) { echo '<a href="/">Home</a>'; } ?> </td>Thanks!
Ryan
July 26, 2011Awesome!
I’m glad it worked for you! Also, it’s good to know these functions are still alive and well in WP 3.x.
Jessica
August 19, 2011Hi–great tutorial! Thanks. I’m just having trouble getting my categories excluded… thanks again, Jessica.
Jessica
August 19, 2011Sorry, meant to specify too that I’ve been building my own theme, & wanted to ask if I could have left a function out or something that would make category exclusion work. Cheers!
Ryan
August 22, 2011Hi Jessica,
Which version of WordPress are you running? Would you also mind sharing the code you’re using? You can use the < pre > tag (without spaces) to wrap your code so it formats nicely.
Abhishek
December 7, 2011Great tip. Thanks a lot!
-Abhi
Rob
January 11, 2012Hello,
Is there a way to use this same feature but apply it to the standard next_posts_link and previous_posts_link to navigate backwards and forwards between pages that display several posts, without having either Previous or Next disappear on the very first and very last pages?
I hope my explanation makes sense.
Thanks so much for your help and time.
Ryan
January 11, 2012Hey Rob,
Your question makes perfect sense; I’m just not sure if there is a function that does what you want. Have you tried asking in the WP forums? Here are three possible solutions:
1. Try getting in touch with Mark Jaquith, lead dev for WordPress. His contact info is here.
2. Try the get_next_post() function. I have no idea if it will work in your case, but I stumbled across it while looking for an answer.
3. Try the Next/Previous Post Link Plus plugin. It may or may not address your specific question, but it looks like it might offer an alternative for you.
Sorry I don’t have a definitive answer — hopefully one of those options helps!
Rob
January 11, 2012Hi Ryan,
Thanks so much for your suggestions.
Its interesting that an available method to solve this is so difficult to find.
I have yet to post this on the WP forums – I’ll try that along with writing to Mark Jaquith.
I did think of a solution, although I am having difficult working out how to do it exactly and I wanted to ask your advice.
Basically my navigation is an include file that consists of ‘Previous’ (next_posts_link) and ‘Next’ (previous_posts_link) that I would like to be shown at all times.
So I was thinking that for the homepage of my website that displays the latest posts in a typical blog fashion, I could include a different navigation (only on the homepage) that would display ‘Previous’ (next_posts_link) and ‘Next’ (with no link attached – just text) so that the ‘Next’ link doesn’t disappear.
How would I do this? Since at the moment my index.php file is acting as the template for all of the pages with blog entries.
Please let me know what you think would be the most logical way to do this.
Thanks so much. I really appreciate your help.
Rob
Rob
January 11, 2012Hi Ryan,
I received some assistance on the wordpress forums.
Here is my post.
& this was the reply containing the solution:
you can build it conditionally based on get_next_posts_link() and get_previous_posts_link(), resp.
Ryan
January 12, 2012Ahh, I wasn’t aware of those two functions. Those should work beautifully. Thank you for sharing, and I’m glad you got things to work!
And in reference to your previous question on putting something just on the homepage, you can use the is_front_page() or is_home() conditionals.
1 pingback
Alex Barber | Digital Artist | WordPress page navigation – modify next and previous post link
June 22, 2011[...] http://www.3roadsmedia.com/blog/improving-wordpress-page-navigation/?replytocom=114 [...]