Wordpress hides the next and previous post links if there are none, but for the sake of visual consistency I'd like to serve up a greyed out version of the link when there is no next or previous post.

I'm assuming a simple if else statement will do, but I don't really do PHP. Any thoughts?

2 Answers 2


The short answer is that there's not really an easy way to do it. There is a solution, but it's sort of ugly. (see waay below.)

A Longer Answer

I'm including this here in the hopes that it's helpful to someone.

Whenever you happen to be using a built in WordPress function, it's instructive to actually go look at what the function does. This is especially true if you wish to modify the output.

So let's track down next_post_link. Here's the source of that function from wp-includes/link-template.php.

 * Display next post link that is adjacent to the current post.                 
 * @since 1.5.0                                                                 
 * @param string $format Optional. Link anchor format.                          
 * @param string $link Optional. Link permalink format.                         
 * @param bool $in_same_cat Optional. Whether link should be in a same category.
 * @param array|string $excluded_categories Optional. Array or comma-separated list of excluded category IDs.
function next_post_link($format='%link &raquo;', $link='%title', $in_same_cat = false, $excluded_categories = '') {
    adjacent_post_link($format, $link, $in_same_cat, $excluded_categories, false);

Not very exciting. Just a wrapper around another function:

function adjacent_post_link($format, $link, $in_same_cat = false, $excluded_categories = '', $previous = true) {
    if ( $previous && is_attachment() )                                         
        $post = & get_post($GLOBALS['post']->post_parent);                      
        $post = get_adjacent_post($in_same_cat, $excluded_categories, $previous);

    if ( !$post )                                                               

    $title = $post->post_title;                                                 

    if ( empty($post->post_title) )                                             
        $title = $previous ? __('Previous Post') : __('Next Post');             

    $title = apply_filters('the_title', $title, $post->ID);                     
    $date = mysql2date(get_option('date_format'), $post->post_date);            
    $rel = $previous ? 'prev' : 'next';                                         

    $string = '<a href="'.get_permalink($post).'" rel="'.$rel.'">';             
    $link = str_replace('%title', $title, $link);                               
    $link = str_replace('%date', $date, $link);                                 
    $link = $string . $link . '</a>';                                           

    $format = str_replace('%link', $link, $format);                             

    $adjacent = $previous ? 'previous' : 'next';                                
    echo apply_filters( "{$adjacent}_post_link", $format, $link );              

The trouble spot is here:

if ( $previous && is_attachment() )                                         
    $post = & get_post($GLOBALS['post']->post_parent);                      
    $post = get_adjacent_post($in_same_cat, $excluded_categories, $previous);

if ( !$post )                                                               

If there's not a next post (what get_adjacent_post does), the function just returns -- bypassing any filters we may want to hook into. Sucks.

A Hackish PHP Solution

Create a wrapper around next_post_link in your theme's functions.php file. Accept all the same arguments as next_post_link. The only difference is that you're going to start an output buffer before calling next_post_link. Then flush the buffer into a variable -- if the variable is empty, replace it with your placeholder/disabled link.

function wpse53800_next_post_link($format='%link &raquo;', $link='%title', $in_same_cat=false, $exclude_cats='')
    // start the output buffer                                                  

    // call next_post_link                                                      
    next_post_link($format, $link, $in_same_cat, $exclude_cats);                

    // flush the output buffer into $rv                                         
    $rv = ob_get_flush();                                                       

    // if there's nothing in the buffer, you can add it                         
        $rv = 'replace this with disabled link';                                
    echo $rv;                                                                   

An Equally Hackish JavaScript (jQuery) Solution

Somewhere in your theme's JS file(s), you can select the next post link container and add a placeholder if there isn't anything.

An example for TwentyEleven:

<script type="text/javascript">                                                 
    jQuery(document).ready(function() {                                         
        var n = jQuery('span.nav-next');                                        
        if(n.length && n.html() == '') {                                        
            n.html('replace this with disabled link');                          

If you don't have a link to the previous or next post, you can replace the missing link with any html content.

    function posts_pagination_output( $template, $class ) {

        $prev = get_previous_post_link();
        $next = get_next_post_link();
        if($prev == ''){$prev = '<span>No previous post.</span>';}else{$prev = '';}
        if($next == ''){$next = '<span>No next post.</span>';}else{$next = '';}

        $template = '
        <nav class="navigation %1$s" role="navigation" aria-label="%4$s">
        <h2 class="screen-reader-text">%2$s</h2>
        <div class="nav-links d-flex justify-content-between py-3">'.$prev.'%3$s'.$next.'</div>

        return $template;
    add_filter( 'navigation_markup_template', 'posts_pagination_output', 99, 2 );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.