How To preserve HTML Tags in WordPress Excerpt Without a Plugin

WordPress Excerpt is a summary of your content. In this tutorial I will show you how to preserve HTML formatting for the automatically generated excerpts without the need of a plugin, and also choose what HTML tags to keep. For a manually typed excerpt, WordPress will keep all HTML formatting you have included in the excerpt. Also in this tutorial, I will show you a different way to change the excerpt_length and the excerpt_more filters.

This tutorial is the second part of my previous post: How To Improve WordPress Excerpt Without a Plugin.

The relationship between the Manual Excerpt and Automatic Excerpt is this: When a post has no manually typed excerpt and the post template uses the the_excerpt() tag, WordPress will automatically generate an excerpt by selecting the first 55 words of the post followed by the unlinked ellipsis “[...]”.

What about a Plugin? Yes, there are plugins that customize WordPress automatically generated excerpt. But haven´t you read my previous post about the disadvantages of unnecessarily adding plugins to your theme?

Manually Typed Post Excerpt

For a manually typed post excerpt, WordPress will keep all HTML tags you included in your excerpt. If you don´t know where and how to add a manual excerpt, read the section “How To: Manually Add a Post Excerpt” in my previous tutorial.

When using the manually typed excerpt, WordPress does not automatically provide a link to a page containing the full post. To generate a link at the end of the excerpt, read the section “How To: Manually Add a Post Excerpt” in my previous tutorial.

Automatically Generated Post Excerpt

In WordPress, if you do not provide a manually written excerpt to a post, WordPress will display an automatically generated excerpt. The problem with that, is WordPress will, by default, display the excerpt with the first 55 words of the post´s content, an un-linked ´[...]´ string at the end, and with all HTML tags stripped from the excerpt´s content. This makes the excerpt one long text paragraph without any line breaks.

In this tutorial, I will show you, how to overcome these shortcomings, and how to preserve all (or some) of the HTML tags in your auto-generated excerpt. All these changes are done in your theme´s functions.php file. Here is How:

Preserve HTML Tags in the Excerpt and Other Settings

Open the functions.php file located in your current theme folder and add (copy and paste) the following code. You can edit lines 22, 25, and 28 accordingly:

MAIN_CODE (Tested on WordPress Version 3.1.3 but it works on any Version >= 1.5.0)

Note: To scroll within the code: You can also click on the code window and use your keyboard´s arrow keys.

<?php
/******************************************************************************
* @Author: Boutros AbiChedid 
* @Date:   June 20, 2011
* @Websites: http://bacsoftwareconsulting.com/ ; http://blueoliveonline.com/
* @Description: Preserves HTML formating to the automatically generated Excerpt.
* Also Code modifies the default excerpt_length and excerpt_more filters.
* @Tested: Up to WordPress version 3.1.3
*******************************************************************************/ 
function custom_wp_trim_excerpt($text) {
$raw_excerpt = $text;
if ( '' == $text ) {
	//Retrieve the post content. 
    $text = get_the_content('');

    //Delete all shortcode tags from the content. 
    $text = strip_shortcodes( $text );

    $text = apply_filters('the_content', $text);
    $text = str_replace(']]>', ']]&gt;', $text);
    
    $allowed_tags = ''; /*** MODIFY THIS. Add the allowed HTML tags separated by a comma.***/
    $text = strip_tags($text, $allowed_tags);
    
    $excerpt_word_count = 55; /*** MODIFY THIS. change the excerpt word count to any integer you like.***/
    $excerpt_length = apply_filters('excerpt_length', $excerpt_word_count); 
    
    $excerpt_end = '[...]'; /*** MODIFY THIS. change the excerpt endind to something else.***/
    $excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end);
    
    $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);
}
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'custom_wp_trim_excerpt');
?>

Watch out with the <!–more–> tag, if you are using the <!–more–> tag in your content, make sure that it resides outside the excerpt; otherwise your excerpt will end without an ending link. If there is a More tag in your post, then the excerpt word count stops at either where the More tag is placed, without the excerpt trailing characters, or your defined excerpt length, whichever comes first.

You can replace lines 42 and 43 of the MAIN_CODE with the following: With the same results.

<?php 
//Replace line 42 and 43 of the MAIN_CODE with a hook with higher priority.
add_filter('get_the_excerpt', 'custom_wp_trim_excerpt', 5);
?>

References:

How To: Preserve HTML Formatting

Why are we doing this? I am taking a different approach than in my previous tutorial, because there is no filter available for the HTML tags like the excerpt_length and excerpt_more filters. Therefore we need to rewrite the wp_trim_excerpt() function and use our function instead of the WordPress default function.

If you want to keep all or some chosen HTML tags. For example if you like to keep the p, a, em, strong, img, tags then find line 22 of the “MAIN_CODE” and replace it with this:

<?php 
//Replace line 22 of the MAIN_CODE with this:
//Separate tags by commas. Add or Remove tags as you wish. 
$allowed_tags = '<p>,<a>,<em>,<strong>,<img>'; 
?>
  1. WordPress counts the content of the HTML tags as part of the excerpt total word count. Therefore you need to be careful what tags you need to add. For example the title attribute in an image or link are counted as part of the excerpt length.
  2. Add the tags that you want to allow separated by comma. Be careful what tags you add because if you have the “continue reading” link and you stop in the middle of a non-closed tag, the link will take its formatting. For instance, if the excerpt stopped somewhere in an open acronym, the link will be formatted like an acronym, and if the excerpt stopped in an open header, the link will take the header´s formatting. And most importantly, if you stop in the middle of a non-closed tag (like an anchor tag) you might be getting XML validation errors/warnings that cause your RSS feed to not work properly. Therefore, test your blog and your RSS feed.

How To: Change the Excerpt Length

NOTE: The excerpt_length filter that I talked about in my previous tutorial, specifically Code1 work fine with the “MAIN_CODE” above. The filter overrides what is assigned in the “MAIN_CODE”. However; why add an unnecessary function that can be done in the “MAIN_CODE”.

If you like to change the automatically generated excerpt length from the default 55 words, find line 25 in the “MAIN_CODE” and replace it with this:

<?php 
//Replace line 25 of the MAIN_CODE with this:	
$excerpt_word_count = 65; /* Choose any number you like. */
?>

How To: Change Excerpt Length Depending on the Category

If you want to modify the excerpt length based on one category, then find line 25 in the “MAIN_CODE” and replace it with this:
Don´t forget to change the category ID to yours.

<?php
//Replace line 25 of the MAIN_CODE with this:
if (in_category(4)) {  //For posts belonging to category ID 4
   $excerpt_word_count = 65; //return 65-word length excerpt.
} else {
    $excerpt_word_count = 40; //for all others, return 45 words.
}
?>

If you want to modify the excerpt length based on multiple categories, then find line 25 in the “MAIN_CODE” and replace it with this:

Don´t forget to change the category IDs to yours.

<?php
//Replace line 25 of the MAIN_CODE with this:
if(in_category(array(4,40))) {  //For posts belonging to category IDs 4 and 40
    $excerpt_word_count = 65; //return 65 words for the excerpt.
} else {
     $excerpt_word_count = 40; //for all others, return 40 words.
}
?>
  1. If there is a More tag in your post, then the excerpt word count stops at either where the More tag is placed, without the excerpt trailing characters, or your defined excerpt length, whichever comes first. Therefore make sure that you place the More tag outside your specified word count.
  2. If you don´t know how to find the Category ID, then read my previous tutorial.

Reference:

How To: Replace the Excerpt More String with a Link

NOTE: The excerpt_more filter that I talked about in my previous tutorial, specifically Code3c work fine with the “MAIN_CODE” above. The filter overrides what is assigned in the “MAIN_CODE”. However; why add an unnecessary function that can be done in our “MAIN_CODE”.

By default WordPress outputs an un-linked “[...]” at the end of each excerpt, which is not useful for Accessibility and SEO purposes. If you want to modify the excerpt more string with a link, then find line 28 in the “MAIN_CODE” and replace it with this:

<?php 
//Replace line 28 of the MAIN_CODE with this: 
$excerpt_end = ' <a href="'. get_permalink($post->ID) . '">' . '&raquo; Continue Reading.' . '</a>'; 
?>

If you want to add the post title to your link in the excerpt, then find line 28 in the “MAIN_CODE” and replace it with this:

<?php 
//Replace line 28 of the MAIN_CODE with this:  
$excerpt_end = ' &#8230;<br /><a href="'. get_permalink($post->ID) . '">' . '&raquo; Continue Reading: '. get_the_title() . '</a>'; 
?>

Reference:

The Code I used for This Blog

Below is the code, that I added to the functions.php file for this Blog.

<?php
/******************************************************************************
* @Author: Boutros AbiChedid 
* @Date:   June 20, 2011
* @Websites: http://bacsoftwareconsulting.com/ ; http://blueoliveonline.com/
* @Description: Preserves HTML formating to the automatically generated Excerpt.
* Also Code modifies the default excerpt_length and excerpt_more filters.
*******************************************************************************/ 
function custom_wp_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);
    
    /***Add the allowed HTML tags separated by a comma.***/
    $allowed_tags = '<p>,<a>,<em>,<strong>';  
    $text = strip_tags($text, $allowed_tags);
    
    /***Change the excerpt word count.***/
    $excerpt_word_count = 60; 
    $excerpt_length = apply_filters('excerpt_length', $excerpt_word_count); 
    
    /*** Change the excerpt ending.***/
    $excerpt_end = ' <a href="'. get_permalink($post->ID) . '">' . '&raquo; Continue Reading.' . '</a>'; 
    $excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end);
    
    $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);
}
remove_filter('get_the_excerpt', 'wp_trim_excerpt');
add_filter('get_the_excerpt', 'custom_wp_trim_excerpt');
?>

And here is an image of the results for the Code above:

Custom WordPress automatically generated excerpt.

Below is an image of the default auto-generated excerpt, if I did not add the code above to this theme´s functions.php file. You will be the judge as to which excerpt is nicer!

Default WordPress automatically generated excerpt.

General Warning

When you add several PHP code blocks in your theme´s funtions.php file, make sure that you don´t leave any whitespace (spaces, newline) before the opening PHP tag or after the closing PHP tag. Like so (the correct way):

<?php 
//Some Code here beetween the opening PHP tag (above) 
//and the closing PHP tag (below)...
?>
<?php 
//Some other Code here ...
?>

In the above code, if you leave any whitespace or a newline between lines 4 and 5, you will get the following error: Warning: Cannot modify header information – headers already sent by (… , in your login screen and after you login to your WordPress dashboard.

General Advice

Keep WordPress Up to Date. If you can, you should always have the latest version of WordPress. Upgrading to the latest version is necessary because upgrades usually include performance and security enhancements and also new features. Go and download the latest version.

Conclusion

This simple code, help you enhance the default WordPress excerpt without the need of a plugin. The automatically generated excerpt is stripped from all HTML tags. In this tutorial, I discussed how to keep HTML formatting in the excerpt (also you get to choose which tags to keep). I also revisited the excerpt_more and excerpt_length filters, and how they can be used in a more efficient way as part of the same code block.

Do you have any other suggestions? or anything else to say? If so, please share your opinion in the comments section. Your opinion matters, unless it is a Spam.

If you found this post useful, please consider: linking back to it, subscribing by email to future posts, or subscribing to the RSS feed to have new articles delivered to your feed reader, or feel free to donate. Thanks!

About the Author |
Boutros is a professional Drupal & WordPress developer, Web developer, Web designer, Software Engineer and Blogger. He strives for pixel perfect design, clean robust code, and user-friendly interface. If you have a project in mind and like his work, feel free to contact him. Connect with Boutros on Twitter, and LinkedIn.
Visit Boutros AbiChedid Website.

89 Responses to “How To preserve HTML Tags in WordPress Excerpt Without a Plugin”

  1. Jennifer says:

    I tried this, because I want to hide blocks of code in excerpts. But if the code is longer than the excerpt, the end tag is missing and the layout breaks.
    Thoughts? Did I do it wrong?

  2. Serigala Militia says:

    the code is so complex dude, but i’ll try for my site.

  3. Sebastian says:

    Thank you for providing this code. Very useful!

  4. Hi!
    I commented earlier with a couple questions … but I’ve run into a different error.

    I want to display a youtube video in an excerpt; I’ve created post formats for my blog so that video posts display just a bit differently than other posts.

    I’ve tried using the tag within the HTML tags allowed section. No dice. :( I’m not sure what else to try – and was hoping you might be able to offer a suggestion?

    Thanks a bunch!
    Kat

  5. Hi there –
    I love your series on customizing the excerpt! I have a different excerpt question for you and wonder if you might have a suggestion for me?

    I think I’ll find that this is part of the post_content and not the_excerpt but here goes:

    When I display an excerpt the featured image is pulled and displays beside the content, including the Title and the Meta information … the bottom wraps around the thumbnail/featured image.

    How can I change this so that the Title and the Meta is actually displayed before the thumbnail and the featured image?

    I’m working on transferring my site to a new server and doing the design before I finalize the domain name update – the development site is located at http://katscafe.triberrvip.com and I would LOVE your suggestions!

  6. Michael Smith says:

    Very helpful.

    Thank you, sir.

  7. Derek says:

    This looks like JUST what I was looking for… but how do you implement this into a page? I’m still farely new to WP but getting better everyday. After putting the above code in the functions.php, how do I call that function to display an excerpt this way? Thanks in advance! – Derek

  8. [...] Preserve HTML Tags in WordPress Excerpt Without a Plugin. [...]

  9. Rob says:

    Boutros,

    First off, great tutorial. For the most part it worked fine but I was getting some wierd error message saying that the header cannot be modifed so every time I tried to save an update it would show the error.

    The end result worked but with the error it slows down the editing process.
    Any ideas?

    Thanks!
    Rob

    • Thanks Rob.
      Please read (and implement) the next section, and let me know if the error goes away (or not). Thanks.

      General Warning:

      When you add several PHP code blocks in your theme´s funtions.php file, make sure that you do NOT leave any white space (spaces, newline) before the opening PHP tag (<?php) or after the closing PHP tag (?>). The correct way is as follows:

      <?php 
      //Some Code here beetween the opening PHP tag (above) 
      //and the closing PHP tag (below)...
      ?>
      <?php 
      //Some other Code here ...
      ?>
      

      In the above code, if you leave any white space or a newline between lines 4 and 5, you will get the following error: “Warning: Cannot modify header information - headers already sent by…

  10. Dave says:

    Will this method work on a Genesis Framework child theme without need for alteration? I have an AgentPress site that I would like to preserve HTML markup on for excerpts. It seems like you know your way around Genesis, so I thought you might be able to answer this before I drop it in the functions file. Thanks!

    -Dave

  11. Afton says:

    Excellent, excellent article! You just saved me days of searching and fumbling! :D Dude, you utterly and totally ROCK!!! Instant bookmark! :D

  12. [...] tutorial is a continuation of my two previous tutorials: How To preserve HTML Tags in WordPress Excerpt and How To Improve WordPress [...]