Function Friday #16: add an accessible post link to manual & automatic excerpts

Function Friday #16

Every Friday, I’m sharing code snippets that I use to customize WordPress. Feedback/suggestions are always welcome! For more information, check out the first post in the series.


When you’re displaying lots of blog posts in a row and you don’t want to show the entire post, the WordPress function the_excerpt will display either the text entered in the “Excerpt” field below the post* (a manual excerpt), or the first 55 words of your post followed by “[…]” (an automatic excerpt):

Default excerpts

*If you don’t see this field, click “Screen Options” in the top right corner while editing a post to enable it.

You might want to change the default number of words, or add a link to the post instead of an ellipsis. While you’re at it, you could also make the post link more useful for visitors that are accessing your site with a screen reader.

It’s easy to hook into and modify the default excerpt with a few filters.

The code

// Set the post excerpt length to 18 words
function drollic_excerpt_length( $length ) {
    return 18;
}
add_filter( 'excerpt_length', 'drollic_excerpt_length' );

// Append Continue reading link to all excerpts
function drollic_continue_reading_excerpt( $excerpt ) {
    $continue_reading = ' <a class="read-more-link" href="' . get_permalink() . '">Continue reading<span class="screen-reader-text"> &ldquo;' . get_the_title() . '&rdquo;</span> &rarr;</a>';
    if ( ! has_excerpt() ) { // Don't append an ellipsis to manual excerpts
        $continue_reading = ' &hellip;' . $continue_reading;
    }
    $excerpt = $excerpt . $continue_reading;
    return $excerpt;
}
add_filter( 'get_the_excerpt', 'drollic_continue_reading_excerpt' );

// Remove the default [...] from automatic post excerpts
function drollic_excerpt_more( $more ) {
    $more = '';
    return $more;
}
add_filter( 'excerpt_more', 'drollic_excerpt_more' );

The first function hooks into excerpt_length and sets it to 18 words instead of the default 55:

// Set the post excerpt length to 18 words
function drollic_excerpt_length( $length ) {
    return 18;
}
add_filter( 'excerpt_length', 'drollic_excerpt_length' );

Next, hook into get_the_excerpt to override the default display of both kinds of excerpts (manual and automatic):

// Append Continue reading link to all excerpts
function drollic_continue_reading_excerpt( $excerpt ) {
    $continue_reading = ' <a class="read-more-link" href="' . get_permalink() . '">Continue reading<span class="screen-reader-text"> &ldquo;' . get_the_title() . '&rdquo;</span> &rarr;</a>';
    if ( ! has_excerpt() ) { // Don't append an ellipsis to manual excerpts
        $continue_reading = ' &hellip;' . $continue_reading;
    }
    $excerpt = $excerpt . $continue_reading;
    return $excerpt;
}
add_filter( 'get_the_excerpt', 'drollic_continue_reading_excerpt' );

The has_excerpt function returns true for posts with manual excerpts, and false for all other posts. If you’ve gone to the trouble of adding text to the “Excerpt” field, you probably used complete sentences, so adding an ellipsis after the excerpt text doesn’t make sense. If you’re relying on WordPress’s automatic excerpts that cut you off at 18 words, though, including an ellipsis will probably look better.

The “Continue reading” link here includes the post’s title inside a special class called screen-reader-text:

<a class="read-more-link" href="' . get_permalink() . '">Continue reading<span class="screen-reader-text"> &ldquo;' . get_the_title() . '&rdquo;</span> &rarr;</a>

Using this code snippet, all of your “Continue reading” links will visually look the same. For someone using a screen reader, however, the post’s title will be read aloud as part of the link.

This means that skipping from link to link won’t just repeat (rather uselessly) “Continue reading”, “Continue reading”, “Continue reading”… it will actually say “Continue reading ‘A post with an automatic excerpt'”.

For the screen-reader-text class to work, you’ll also need this in your CSS:

.screen-reader-text {
    clip: rect(1px 1px 1px 1px); /* IE 6-7 */
    clip: rect(1px, 1px, 1px, 1px);
    height: 1px!important;
    overflow: hidden;
    position: absolute;
    width: 1px!important;
}

Don’t use display: none as that will hide the content from everyone, including screen readers!

Finally, prevent the default “[…]” from being added to automatic excerpts, using the excerpt_more filter:

// Remove the default [...] from automatic post excerpts
function drollic_excerpt_more( $more ) {
    $more = '';
    return $more;
}
add_filter( 'excerpt_more', 'drollic_excerpt_more' );

An important distinction here is that with excerpt_more, you’re just modifying what comes after the automatic excerpt. With get_the_excerpt, you’re actually modifying the whole excerpt, so you want to add your “Continue reading” link onto the existing excerpt by concatenating the two.

Your posts will now have matching “Continue reading” links, with an ellipsis after the automatic excerpt:

Customized excerpts

Where does it go?

I usually put this code in my theme’s functions file, but it could also work in a functionality plugin, with the caveat that your blog has to be using the_excerpt instead of the_content for it to have any effect. If you do include this in a functionality plugin, make sure the CSS for the screen reader text class is loaded as well. There’s more info about both of these options in the first Function Friday post.

Resources

6 Responses to “Function Friday #16: add an accessible post link to manual & automatic excerpts”

  1. Hi! Thanks – this is really useful!

    Is it possible to have the “continue reading” link only show if the manual excerpt is filled out? I’ve upped the automatic excerpt to 500 words so that the full post will show if there’s no manual excerpt, but I don’t want a “continue reading” link after the full content. I’ve read a lot of how-to articles and I can’t figure out if this is possible with WP.

    • For sure! You can modify the second function like this:

      // Append Continue reading link to all excerpts
      function drollic_continue_reading_excerpt( $excerpt ) {
          $continue_reading = ' <a class="read-more-link" href="' . get_permalink() . '">Continue reading<span class="screen-reader-text"> &ldquo;' . get_the_title() . '&rdquo;</span> &rarr;</a>';
          if ( has_excerpt() ) { // Only append the link to manual excerpts
              $excerpt = $excerpt . $continue_reading;
          }
          return $excerpt;
      }
      add_filter( 'get_the_excerpt', 'drollic_continue_reading_excerpt' );

      One note is that the_excerpt() isn’t quite the same thing as the_content() even if you increase the word count to include all text – it strips tags, doesn’t run shortcodes, etc. So depending on your post content it might be worth modifying this even further to have it return the_content instead of the_excerpt unless a manual excerpt is set. That would need some more testing though!

  2. Awesome thanks – I’ll try this. I don’t want to use the_content() as many of the posts will have videos and I’ve already sorted that part out with featured videos. I didn’t see this till now! I’m going to blame the BC election for totally derailing this week. Thanks again!

    • Makes sense, let me know how it goes! And no worries – I should have emails send when there’s a comment reply instead of having to check back. Putting it on my to-do list!

Leave a Reply

Your email address will not be published. Required fields are marked *