Next/previous posts links with thumbnails and excerpts

[Blaugust Day 20]

I’m going to warn you right now: if you come here to read about games and my random musings, you’ll likely want to skip this post. It’s all about teh code. WordPress code to be exact.

When I was creating my last redesign, I came to the portion of the single post template where you add the links for the next and previous posts. I could have gone with some standard WordPress tags, but then I had the idea that it would be pretty cool to not just show the title of the next/previous posts, but also an excerpt and a thumbnail. Something that looked like this:


Getting those post titles is super easy and the thumbnails weren’t too hard, but the excerpt was a pain in the arse. It took many days of Google-ing before I was able to put together some workable code. I’ll give you the whole section of code first, and then highlight what certain parts do.

<div class="navigation">
  <div class="nav-newer clear-fix">
    <?php $nextPost = get_next_post(); if($nextPost): ?>
      <?php if (has_post_thumbnail( $nextPost->ID ) ): ?>
        <?php $nextthumbnail = wp_get_attachment_image_src( get_post_thumbnail_id($nextPost->ID), 'secondary-thumb' ); $nextthumbnail = $nextthumbnail[0]; ?>
      <?php else :
        $nextthumbnail = get_stylesheet_directory_uri() . '/images/default-featured.jpg'; ?>
      <?php endif; ?>
      <div class="thumb" style="background-image:url(<?php echo $nextthumbnail; ?>);"><a href="<?php echo get_permalink(get_adjacent_post(false,'',false)); ?>"></a></div>
      <div class="entry">
        <div class="label">Next post</div>
        <h4><?php next_post_link('%link'); ?></h4>
        <?php setup_postdata( $nextPost ); the_excerpt(); wp_reset_postdata(); ?>
    <?php endif; ?>
  <div class="nav-older clear-fix">
    <?php $prevPost = get_previous_post(); if($prevPost): ?>
      <?php if (has_post_thumbnail( $prevPost->ID ) ): ?>
        <?php $prevthumbnail = wp_get_attachment_image_src( get_post_thumbnail_id($prevPost->ID), 'secondary-thumb' ); $prevthumbnail = $prevthumbnail[0]; ?>
      <?php else :
        $prevthumbnail = get_stylesheet_directory_uri() . '/images/default-featured.jpg'; ?>
      <?php endif; ?>
      <div class="thumb" style="background-image:url(<?php echo $prevthumbnail; ?>);"><a href="<?php echo get_permalink(get_adjacent_post(false,'',true)); ?>"></a></div>
      <div class="entry">
        <div class="label">Previous post</div>
        <h4><?php previous_post_link('%link'); ?></h4>
        <?php setup_postdata( $prevPost ); the_excerpt(); wp_reset_postdata(); ?>
    <?php endif; ?>

The next and previous sections have very similar code so I’ll just explain the next parts.

<?php $nextPost = get_next_post(); if($nextPost): ?> ... <?php endif; ?>

This IF loop gets the next posts information and assigns it to the nextPost variable.

<?php if (has_post_thumbnail( $nextPost->ID ) ): ?>

Checks if the post has a thumbnail (AKA featured image).

<?php $nextthumbnail = wp_get_attachment_image_src( get_post_thumbnail_id($nextPost->ID), 'secondary-thumb' ); $nextthumbnail = $nextthumbnail[0]; ?>

If it does, the image is retrieved at the size of “secondary-thumb“, which is set in the functions.php using add_image_size( 'secondary-thumb', 500, 300 );.

<?php else : $nextthumbnail = get_stylesheet_directory_uri() . '/images/default-featured.jpg'; ?>

If the post doesn’t have a thumbnail, the default thumbnail in my theme’s image folder is used instead.

<div class="thumb" style="background-image:url(<?php echo $nextthumbnail; ?>);">

Uses whichever thumbnail was specified as the background for the thumb div.

<a href="<?php echo get_permalink(get_adjacent_post(false,'',false)); ?>"></a>

Adds a link to the next post. This one doesn’t contain any text because it’s just a transparent link that overlays the thumbnail image. To get the previous post’s link, the last false needs to be changed to true.

<h4><?php next_post_link('%link'); ?></h4>

Gets the next post’s title and links it to the post.

<?php setup_postdata( $nextPost ); the_excerpt(); wp_reset_postdata(); ?>

This is the part that took me a really long time to work out. The issue is that the_excerpt doesn’t have any parameters so there’s no way to specify which post you’d like it to take an excerpt from. It just assumes you’d like to use the current post, whereas I wanted it to use the next post. At first I tried to emulate the_excerpt by using a combination of wp_trim_words and wp_strip_all_tags but I still couldn’t quite get it to be the same output as what I wanted. Luckily, I found out about setup_postdata which allows you to set the global post data as something other than the current post. And wp_reset_postdata resets the post data to its original state.

That’s pretty much it! If you’d like to see my CSS as well, here it is:

/* Previous/next post navigation */
.navigation .nav-newer, .navigation .nav-older { max-width:1000px; margin:50px auto 0 auto; background-color:#ffffff; color:#404040; position:relative; }
.navigation .thumb { background-size:cover; background-position:center center; background-repeat:no-repeat; width:50%; position:absolute; height:100%; top:0; left:0; transition: all 0.5s; -o-transition: all 0.5s; -moz-transition: all 0.5s; -webkit-transition: all 0.5s; }
.navigation .nav-newer:hover .thumb, .navigation .nav-older:hover .thumb { opacity:0.8; transition: all 0.5s; -o-transition: all 0.5s; -moz-transition: all 0.5s; -webkit-transition: all 0.5s; }
.navigation .thumb a { display:block; height:100%; width:100%; }
.navigation .entry { width:50%; float:right; box-sizing:border-box; -moz-box-sizing:border-box; -webkit-box-sizing:border-box; padding:30px; }
.navigation .entry a { color:#607624; }
.navigation .entry a:hover { color:#000000; }
.navigation .entry h4 { text-align:center; margin-top:0; font-size:1.8em; }
.navigation .entry h4 a { text-decoration:none; }
.navigation .nav-newer .thumb { right:0; left:auto; }
.navigation .nav-newer .entry { float:none; }
.navigation .entry .label { font-family:"Raleway", Arial, sanserif; font-weight:300; font-size:90%; text-transform:uppercase; }
.navigation .entry .label:after { content:""; height:1px; width:50%; display:block; background-color:#C2C2C2; margin:10px 0; }
.navigation .nav-older .entry .label { text-align:right; }
.navigation .nav-older .entry .label:after { margin-left:auto; }

Happy coding!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.