Back to Top

WordPress’s Fancy Excerpt for Your Site

Previous Post:

WordPress’s Fancy Excerpt for Your Site

Post excerpts might be much less used than the <!-- more --> separator, but they still play a key role on any WordPress website/blog nowadays. The fact that WordPress strips all HTML markups from generated excerpts (i.e. when the excerpt field is empty) somehow makes them look bad. Many webmasters decide to format those excerpts in their own ways, and this tip will show you how.

First of all, we will have to remove the default formatting function that is applied to get_the_excerpt hook, by adding this line to your theme’s functions.php:

  1. remove_filter('get_the_excerpt', 'wp_trim_excerpt');
remove_filter('get_the_excerpt', 'wp_trim_excerpt');

Next, we add a new filter to get_the_excerpt hook, that filter will be our own formatting function, called bwp_trim_excerpt:

  1. add_filter('get_the_excerpt', 'bwp_trim_excerpt');
add_filter('get_the_excerpt', 'bwp_trim_excerpt');

bwp_trim_excerpt itself should be similar to wp_trim_excerpt, but you can customize it freely to suit your needs. An example bwp_trim_excerpt might look like this:

  1. function bwp_trim_excerpt($text)
  2. {
  3.     $raw_excerpt = $text;
  4.     if ( '' == $text ) {
  5.         $text = get_the_content('');
  6.         $text = strip_shortcodes( $text );
  7.         $text = apply_filters('the_content', $text);
  8.         $text = str_replace(']]>', ']]&gt;', $text);
  9.         $text = strip_tags($text, '<em><strong><i><b>');
  10.         $excerpt_length = apply_filters('excerpt_length', 55);
  11.         $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
  12.         $words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
  13.         if ( count($words) > $excerpt_length ) {
  14.             array_pop($words);
  15.             $text = implode(' ', $words);
  16.             $text = $text . $excerpt_more;
  17.         } else {
  18.             $text = implode(' ', $words);
  19.         }
  20.     }
  21.     return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
  22. }
function bwp_trim_excerpt($text)
{
	$raw_excerpt = $text;
	if ( '' == $text ) {
		$text = get_the_content('');
		$text = strip_shortcodes( $text );
		$text = apply_filters('the_content', $text);
		$text = str_replace(']]>', ']]&gt;', $text);
		$text = strip_tags($text, '<em><strong><i><b>');
		$excerpt_length = apply_filters('excerpt_length', 55);
		$excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
		$words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
		if ( count($words) > $excerpt_length ) {
			array_pop($words);
			$text = implode(' ', $words);
			$text = $text . $excerpt_more;
		} else {
			$text = implode(' ', $words);
		}
	}
	return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
}

I just basically copy wp_trim_excerpt() from wp-includes/formatting.php to theme’s functions.php, modify it a little bit and then rename it to bwp_trim_excerpt(). Such minor change (as shown in the highlighted line) allows you to effectively retain both bold and italic text.

Now another related thing is if you use get_the_excerpt()1 instead of the_excerpt()2 in your theme’s files, you will have a raw excerpt, with no auto paragraph, no smiley conversion, etc. To fix that, simply use this:

  1. add_filter('bwp_trim_excerpt', 'wptexturize');
  2. add_filter('bwp_trim_excerpt', 'convert_smilies');
  3. add_filter('bwp_trim_excerpt', 'convert_chars');
  4. add_filter('bwp_trim_excerpt', 'wpautop');
  5. add_filter('bwp_trim_excerpt', 'shortcode_unautop');
add_filter('bwp_trim_excerpt', 'wptexturize');
add_filter('bwp_trim_excerpt', 'convert_smilies');
add_filter('bwp_trim_excerpt', 'convert_chars');
add_filter('bwp_trim_excerpt', 'wpautop');
add_filter('bwp_trim_excerpt', 'shortcode_unautop');

and you don’t have to worry about formatting anymore:

  1. $excerpt = get_the_excerpt();
  2. // do something with the $excerpt variable
  3. // when done, display your excerpt, formatted
  4. echo apply_filters('bwp_trim_excerpt', $excerpt);
$excerpt = get_the_excerpt();
// do something with the $excerpt variable
// when done, display your excerpt, formatted
echo apply_filters('bwp_trim_excerpt', $excerpt);

No need for a plugin, eh?

References

  1. http://codex.wordpress.org/Function_Reference/get_the_e ... he_excerpt []
  2. http://codex.wordpress.org/Template_Tags/the_excerpt []
Print Article Trackback Trackback to this Article   Subscribe to Comments RSS Subscribe to Comments RSS

24 Opinions for WordPress’s Fancy Excerpt for Your Site

  1. User's Gravatar
    1
    Andreas August 1, 2011 at 5:06 pm – Permalink

    Works like a charm! Thank you – this saved me a lot of headache!

  2. User's Gravatar
    2
    tmax October 8, 2011 at 4:39 am – Permalink

    NOOB here can you tell me is this right …are all these going into the functions.php? what am i missing?

    • User's Gravatar
      3
      OddOneOut October 8, 2011 at 1:19 pm – Permalink

      Yes, functions.php :).

      • User's Gravatar
        4
        tmax October 8, 2011 at 7:19 pm – Permalink

        @oddoneout if i am using a parent child theme which functions.php should i tweak the code in?

        id this input correct for the functions.php

        1. remove_filter('get_the_excerpt', 'wp_trim_excerpt');
        2.  
        3. add_filter('get_the_excerpt', 'bwp_trim_excerpt');
        4.  
        5. function bwp_trim_excerpt($text)
        6. {
        7.     $raw_excerpt = $text;
        8.     if ( '' == $text ) {
        9.         $text = get_the_content('');
        10.         $text = strip_shortcodes( $text );
        11.         $text = apply_filters('the_content', $text);
        12.         $text = str_replace(']]>', ']]>', $text);
        13.         $text = strip_tags($text, '<em><strong><i><b>');
        14.         $excerpt_length = apply_filters('excerpt_length', 55);
        15.         $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
        16.         $words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
        17.         if ( count($words) > $excerpt_length ) {
        18.             array_pop($words);
        19.             $text = implode(' ', $words);
        20.             $text = $text . $excerpt_more;
        21.         } else {
        22.             $text = implode(' ', $words);
        23.         }
        24.     }
        25.     return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
        26. }
        27. add_filter('bwp_trim_excerpt', 'wptexturize');
        28. add_filter('bwp_trim_excerpt', 'convert_smilies');
        29. add_filter('bwp_trim_excerpt', 'convert_chars');
        30. add_filter('bwp_trim_excerpt', 'wpautop');
        31. add_filter('bwp_trim_excerpt', 'shortcode_unautop');
        32.  
        33. $excerpt = get_the_excerpt();
        34. // do something with the $excerpt variable
        35. // when done, display your excerpt, formatted
        36. echo apply_filters('bwp_trim_excerpt', $excerpt);
        remove_filter('get_the_excerpt', 'wp_trim_excerpt');
        
        add_filter('get_the_excerpt', 'bwp_trim_excerpt');
        
        function bwp_trim_excerpt($text)
        {
            $raw_excerpt = $text;
            if ( '' == $text ) {
                $text = get_the_content('');
                $text = strip_shortcodes( $text );
                $text = apply_filters('the_content', $text);
                $text = str_replace(']]>', ']]>', $text);
                $text = strip_tags($text, '<em><strong><i><b>');
                $excerpt_length = apply_filters('excerpt_length', 55);
                $excerpt_more = apply_filters('excerpt_more', ' ' . '[...]');
                $words = preg_split("/[\n\r\t ]+/", $text, $excerpt_length + 1, PREG_SPLIT_NO_EMPTY);
                if ( count($words) > $excerpt_length ) {
                    array_pop($words);
                    $text = implode(' ', $words);
                    $text = $text . $excerpt_more;
                } else {
                    $text = implode(' ', $words);
                }
            }
            return apply_filters('wp_trim_excerpt', $text, $raw_excerpt);
        }
        add_filter('bwp_trim_excerpt', 'wptexturize');
        add_filter('bwp_trim_excerpt', 'convert_smilies');
        add_filter('bwp_trim_excerpt', 'convert_chars');
        add_filter('bwp_trim_excerpt', 'wpautop');
        add_filter('bwp_trim_excerpt', 'shortcode_unautop');
        
        $excerpt = get_the_excerpt();
        // do something with the $excerpt variable
        // when done, display your excerpt, formatted
        echo apply_filters('bwp_trim_excerpt', $excerpt);
        • User's Gravatar
          5
          OddOneOut October 8, 2011 at 7:47 pm – Permalink

          You should put those codes into your child theme’s functions.php, and yes, they look correct.

          • User's Gravatar
            6
            tmax October 8, 2011 at 7:55 pm – Permalink

            @OddOneOut what i have a custom post type too namesd products which is a child theme and its stripping all my html markup in the post.. what do i do in this case to retain my markup??

        • User's Gravatar
          7
          OddOneOut October 8, 2011 at 8:11 pm – Permalink

          Hmm if your theme uses either the_excerpt or get_the_excerpt, it should have worked already. Btw, you should remove line 33 to line 36 in the above codeblock, they are meant for your actual theme’s files (e.g. index.php) not functions.php.

          • User's Gravatar
            8
            tmax October 8, 2011 at 10:22 pm – Permalink

            @odd one out u tried all options you suggested.. the markup is still getting stripped in my custom post description… is there anything i can try more?

        • User's Gravatar
          9
          OddOneOut October 9, 2011 at 8:30 pm – Permalink

          Please use the contact form and send your functions.php file along with the theme files you’re having trouble with and I will have a look when possible.

  3. User's Gravatar
    10
    Jeff Friend October 28, 2011 at 10:54 pm – Permalink

    Great tutorial…thank you. I am consistently amazed by the power of the functions.php file! I’d really like to find a way to have different verbiage for my excerpts link text (one for the home page, and one for the blog page). I suppose I could do this with the CSS content property, but that won’t work for IE7 or older. Any ideas?

    • User's Gravatar
      11
      OddOneOut October 29, 2011 at 5:49 pm – Permalink

      Hi Jeff,

      It’s very easy to do so. In the bwp_trim_excerpt function you find above, search for:

      1. $excerpt_length = apply_filters('excerpt_length', 55);
      $excerpt_length = apply_filters('excerpt_length', 55);

      and then replace that line with:

      1. if (is_home())
      2.     $default_length = 55;
      3. else if (is_page())
      4.     $default_length = 100;
      5. else
      6.     $default_length = 50;
      7. $excerpt_length = apply_filters('excerpt_length', $default_length);
      if (is_home())
      	$default_length = 55;
      else if (is_page())
      	$default_length = 100;
      else
      	$default_length = 50;
      $excerpt_length = apply_filters('excerpt_length', $default_length);

      Save the file and enjoy :).

  4. User's Gravatar
    12
    Jeff Friend October 30, 2011 at 9:01 pm – Permalink

    Thanks for the code example. I think that set me on the right track! What I need is different verbiage for my excerpts link text (ie; home page excerpt link reads ‘Read more in our blog’, and the blog page excerpt links say ‘Read more’). This seems to do the trick:

    1. <?php
    2. function new_excerpt_more($post) {
    3.     if (is_home())
    4.     return '... (<a>' . '>' . 'Read more...' . '</a>)';
    5.     else if (is_page())
    6.     return '... (<a>' . '>' . 'Read more...' . '</a>)';
    7.     else
    8.     return '... (<a>' . '>' . 'Read more in our blog...' . '</a>)';
    9. }
    10. add_filter('excerpt_more', 'new_excerpt_more');
    11. ?>
    <?php
    function new_excerpt_more($post) {
    	if (is_home())
    	return '... (<a>' . '>' . 'Read more...' . '</a>)';
    	else if (is_page())
    	return '... (<a>' . '>' . 'Read more...' . '</a>)';
    	else
    	return '... (<a>' . '>' . 'Read more in our blog...' . '</a>)';
    }
    add_filter('excerpt_more', 'new_excerpt_more');
    ?>
    • User's Gravatar
      13
      OddOneOut October 30, 2011 at 10:26 pm – Permalink

      Sorry for misunderstanding. Anyway, you got that right!

  5. User's Gravatar
    14
    zymatas April 4, 2012 at 12:10 am – Permalink

    Hi, thanks for code. but could you write the code how to make unlimited length ?

  6. User's Gravatar
    15
    Aahan April 5, 2012 at 8:18 pm – Permalink

    Works like a charm! Thanks for the simple tut.

  7. User's Gravatar
    16
    Aahan April 7, 2012 at 4:46 pm – Permalink

    Okay, I am really fortunate that I came across this bug while (probably) no one else did.

    The problem with enabling formatting in post excerpts is that, if the text that is formatted by a tag (be it <b>, <strong>, <i>, <em>, ...</em></i></strong></b>) is cutoff by the excerpt, your whole page’s formatting will be overridden by that tag.

    I believe that’s the reason why formatting for excerpts isn’t enabled by default. It would be great if Khang can provide a workaround, though. :)

    • User's Gravatar
      17
      OddOneOut April 8, 2012 at 10:22 am – Permalink

      Hey Aahan,

      It’s not actually a bug, but rather a missing feature. Of course there are workarounds such as detecting missing closing tags, using an array to save the position of those tags, etc. but they would add unnecessary complexity to the function IMO.

      There’s however a trick you can use: use the same tags two times! So if your bold tag is cutoff, just use two of them, like this: <b>cutoff here</b> <b>continue here, this will not be included in the excerpt</b>.

  8. User's Gravatar
    18
    Richard April 15, 2012 at 6:51 pm – Permalink

    Many thanks for this trick. I really want to be able to display the first image, or the feature image as thumb in my excerpts, as well as doing the other formatting you’ve added. Any chance of a code update for that?
    Thank-you

  9. User's Gravatar
    20
    Richard April 16, 2012 at 12:33 am – Permalink

    Hi, many thanks for your reply and link. Maybe I should use the_content and truncate it somehow. Basically, I’m looking for a post list on the front page with the first post images and a limited text word count for the post.

  10. User's Gravatar
    21
    WordPress Designer September 7, 2012 at 3:02 am – Permalink

    Thanks for the great tip! In my case things don’t usually work just by copying and pasting, but this did the trick. Thanks for all the help and I’m sure I’ll be back to copy this again.

  11. User's Gravatar
    22
    adnil February 4, 2013 at 11:42 pm – Permalink

    I would like the ‘[…]’ as a link to the full text. Is it possible to put something like this
    <a>ID) . '">Continue Reading...</a> into the code? How would I put it?
    Any help would be appreciated.

  12. User's Gravatar
    24
    Bogdan Günther November 14, 2013 at 10:09 pm – Permalink

    Thank you, just what I was looking for!

Speak Up Your Mind!

An asterisk (*) indicates a required field and must be filled.




  • Web page and e-mail addresses turn into links automatically.
  • Wrap codes in: <code lang=""></code> or <pre lang="" extra="">
  • Lines and paragraphs break automatically.

Next Post: