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(']]>', ']]>', $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:
- wp_trim_excerpt()
- get_the_content()
- strip_shortcodes()
- apply_filters()
- the_content()
- str_replace()
- strip_tags()
- excerpt_length()
- excerpt_more()
- implode()
- remove_filter()
- add_filter()
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>'; ?>
- 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.
- 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. } ?>
- 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.
- 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) . '">' . '» 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 = ' …<br /><a href="'. get_permalink($post->ID) . '">' . '» 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(']]>', ']]>', $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) . '">' . '» 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:
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!
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.
Hi Boutros!
This is an excellent article. Really helpful.
I am trying to do something slightly different, and was hoping you could give me a step in the right direction. Rather than just stripping out the (heading) tags from the excerpt, I would like to strip out the heading completely. What code would I use for something like that?
Thanks
Kat
Hi Kat,
I am a bit confused with your question. In this post I am trying to preserve the tags.
You said: “I would like to strip out the heading completely”.
What do you mean by that? Can you give me an example?
Do you mean for instance if there is an h1 in the excerpt: <h1>Header1 Content here</h1>
You also want not to show the statement:”Header1 Content here”, which usually appears as unformatted text.
Let me know.
Boutros.
Hi Boutros,
You’re right; I would like to remove both the tag and the actual “Header1Content Here”.
All the headings used for my blog are only there to split the content into readable chunks, it can be easily read without the headings; in fact having some headings converted to straight text in the excerpt could confuse the reader and make the content look poorly written on my part.
I assumed that a similar sort of technique of creating allowed tags and using filters could also be used for the reverse; to determine where the specific tags are and to then remove the content appropriately instead of perserving.
I haven’t delved this deep into WordPress and custom excerpts before, so if you know a way in which something like would be done I would really appreciate the tip.
Thanks
Kat
Hi kat,
I got your point. I am sure that it can be done, but not sure how?
I opened a thread for you in WordPress support, hopefully you can get the answer you want.
I am also interested to know the answer.
http://wordpress.org/support/topic/remove-content-within-the-header-tags-in-the-excerpt
A year ago, another WordPress user posted a similar problem but with no response.
http://wordpress.org/support/topic/remove-content-from-excerpt
Boutros.
Check out my latest tutorial: How To Remove Header Tags and Their Content in WordPress Excerpt
Hope this helps.
Boutros.
Cool method. I tried but unfortunately. all of my post are leaving blank space before and after excerpts. the space varies in each post thats why I even can’t use css -ve margins to handle it. some of posts are having more than 300px of space.
please let me what to do/
I tried both codes that are mentioned in this post. check out the image: http://i.imgur.com/DlyE9.jpg
Hi Muhammad,
I can’t tell from just looking at a picture what’s the problem.
If you are using a free WordPress theme, share it if you like and I will take a look. Also what Website you are referring to?
Thanks.
Hi Boutros,
Thanks for replying. I’m using a customized theme based on wpzoom framework. here is my function.php. and also check the space on site.
What is your Website?
my website is bonjourlife.com please check.
sorry again. I just noticed that using your method is importing whole post at homepage.. the text appears to the limit set in functions.php whereas the rest of post remains hidden including all images of posts.
I also noticed that it do not occur when I use 60 words excerpts. but whenever I increase it to 100, 300, 500 words. the problem occurs.
Hi Waqas,
I couldn’t tell exactly what the problem is in your case. This is the first time I hear about this behavior behavior due to my code.
I noticed that your posts have little text to start with, 75 words or less and sometimes 1 line of text. So probably it is best to let WordPress handle the excerpt length (default is 55 words).
This means that you can comment out the 2 lines of code (lines 25 and 26) of the “MAIN_CODE”.
There might also be a conflict with your theme that leads to the spacing issue shown in your image. I can’t tell exactly.
By the way, if you use my code in your ‘function.php’ file, make sure to keep the Author’s section intact (it can’t be removed), see terms of use.
Hope this helps,
Boutros.
Yes, I’ve changed it to 55. its working fine.
sorry, my intentions were not bad. I removed that just for testing. I even tried removing line break in code to remove that spaces :D
added your credit :)
Regards. Thanks for the code and support.
sorry again.
I’ve found the problem and solution.
Your code wasn’t problematic but my silly site. Actually I recently transferred by blog from blogger to wordpress. The problem was the “page break” tag in posts. The conversion left that blogger page break tag “<a><a>”
on exceeding excerpts limit somewhere blogger and wordpress started wrestling in the code. and in the result the wordpress was loading full posts with all images and load.
To solve the prob I just triggered the following sql query from phpmyadmin to replace the
<a><a>
with<!--more-->
UPDATE wp_blsmposts SET post_content = REPLACE(post_content, '<a><a>', '<!--more-->')
Everything is fine now.
Thanks again for your code and support
That’s great Waqqas. I am glad that you figured it out.
I always thought that this behavior has to do with your site.
Thanks so much; your solution was exactly what I was looking for! It was driving me crazy to have blockquotes lose all their separate formatting right on my main page. They looked terrible! Thanks for the fix!
You’re welcome Laura. I know what you mean.
Hi Boutros:
Your method works great. However I have a problem when my post contains CJK characters. It is not able to count the words and it will display all the characters. Any way to overcome this problem?
Thanks kentzo for your feedback. I only tested the code for English words, I am not sure what’s the solution for CJK (Chinese Japanese Korean) characters.
I am using common WordPress functions. Why don’t you try at WordPress forum for that, and if you find a solution, please share it here for everybody else to learn.
http://wordpress.org/support/forum/how-to-and-troubleshooting
Thanks.
Boutros.
I found a plugin by this guy http://code.jellycan.com/ml-fancy-excerpt/ . I try to search around and it seems to me that count($word) is unable to count the word correctly as it does not see a space in the excerpt. Currently I am using this jellycan plugin to solve my problem. Hope I can integrate his method to yours. However I need to understand what he is doing first.
Great post, thank you! Very useful, it’s great to be able to preserve the HTML Formatting.
Just a question : I would like to change the Excerpt Length only (!) on the homepage but… when I replace ‘in_category()’ by ‘is_home()’ or ‘is_home() && in_category(1)’ nothing happen… Any ideas? Thank you again!
Thanks for your feedback.
If you want to modify only the Excerpt Length, check (Code1) in my previous related tutorial for that: How To Improve WordPress Excerpt Without a Plugin
Code1 should be added to your theme’s functions.php.
If that’s does not work for you, then there is a conflict with another function in your theme that is doing the same thing (start checking in your theme’s “functions.php” file).
Else for last resort, share your Free WordPress theme (that I can download) and I can take a look.
Hope this helps.
Boutros.
Same problem, ‘is_home()’ is not recognised… I wrote :
and… nothing! + when I replace ‘is_home()’ by ‘is_category()’ that works perfectly. Very strange… Thank you again anyway! I will let you know if I find a solution. All the best.
Can you add this before you call the function.
<?php wp_reset_query(); ?>
See if this works.
http://codex.wordpress.org/Function_Reference/wp_reset_query
Boutros.
I found the trick! I removed ‘Code1′ from functions.php and added it directly in my index page just after the ‘query_posts’. Maybe a little messy but that works!
‘wp_reset_query()’ was killing the ‘query_posts’. Thanks again for your hack, very very useful! All the best.
That’s great!
Great post, and your instructions are clear and easy to follow. This is a great little change, as I am always looking to add a little more horsepower to WordPress.
When people land on category pages, now I have more control over emphasizing certain words to make them stand out. This means I don’t have to noindex my category pages just because they are unpleasant!
-Joe
When I add your code to the latest functions.php in the Suffusion theme (Suffusion 3.9.6 in WordPress 3.3.1), it does nothing. Your custom_wp_trim_excerpt function is never executed. Any idea what’s wrong?
S
Actually, your routine is getting executed, but the excerpt text that is passed to it is already filtered so the bulk of your routine is never executed. Strange.
S
Hi Slim,
Sorry for my late response.
I temporarily installed the “Suffusion 3.9.6″ theme (http://wordpress.org/extend/themes/suffusion). The theme already preserves HTML Tags in WordPress Excerpt (the code is already included). Any HTML formatting that you add prior to the “Continue reading” (including images) will be preserved.
There is no need to add my code.
Please See the Images below, when I temporarily changed my blog’s theme to “Suffusion” (you could see bolded text, paragraphs, images and links):
Let me know if you have other questions.
Boutros.
Hey its really great. this code is really works awesome. i just want to say thank you Boutros.
Hello Boutros and as always thanks again. If you could help me I’d be grateful. Attached is the zip of the theme so you can work there.
Thank you for all the help you are giving to me and for the time you’re working hard for me.
Thanks.
Andrea
Hi Andrea,
I did some changes of your Vulcan theme. The only file that needs to be changed is located in “functions/theme-functions.php”. I already made the changes on your WP dashboard.
The 2 links you gave me for testing are working now.
I added comments on the file for you to understand.
Boutros.
Hi Boutros and thanks again for your help, I really appreciate it. If you want you can work directly on my blog. The address is (removed)
I’ve created for you a user as admin so you can work as you want.
As you’ll see the function.php already has your code in it. The pages where I need the automatic excerpt preserve the HTML are: (removed)
Thank you
Andrea
Hi Andrea,
I think I figured it out. But I can’t be sure unless I test some more. Now I am getting an error (and I don’t have the original files to restore).
Can you restore the “theme-functions.php” and “functions.php” to what they were prior to my changes. It is not letting me do it in the dashboard (always a bad idea to modify files in the dashboard for an active theme, I should have known better).
Upload the original files to the server using your FTP and you should be set to go.
But I think here is your problem:
If you go to “theme-functions.php” you will notice that there is a function that disable Excerpt formatting. This function needs to be removed (or better, commented out), it is basically overwriting my code.
In your case, I think that my code should be added to the “theme-functions.php” and NOT to the “functions.php”. Like the case of Child themes.
I don’t speak Italian, and working in your WordPress dashboard was challenging. But thanks to my French and Google translator I kind of managed.
Also I never use the WordPress dashboard to edit theme files, I usually use Dreamweaver and upload to the Server.
Please let me know If that fixed your problem, by commenting on my Blog or replying here.
Thanks,
Boutros
Thank you Boutros! Just one last favour. Attached you can find the 2 original files (removed). Can you try to figure it out? I’m not so expert with PHP….
Thanks
Andrea
Hi Andrea,
The issue here is your WordPress theme and how it is coded and Not WordPress. In “theme-functions.php” file you have 2 functions that are in direct conflict with my code that either need to be removed or modified to fit with my code.
The 2 functions are: “function excerpt()” and “theme_formatter()” (the latter can be safely commented out but the first can’t since it causes errors without it. It needs to be merged with my code.)
Probably there are more functions in this Vulcan theme that also need editing, I couldn’t check all the files.
So you have 2 choices, either:
1. Don’t use my code and accept what the theme offers you.
2. Or, Try to play around with the code. My code needs to be placed in “admin-functions.php?” file or “theme-functions.php” file but definitely NOT in “functions.php” file.
When I have time, I might to be able to help more, but like I said I am not comfortable with doing things in the dashboard (and Italian too) and also I need to see the documentations of the theme.
Every coding error in the dashboard, I get locked out (meaning the error does not clear unless you re-upload the file to the server through FTP. This is what you need to do now: put the original “theme-functions.php” file back using FTP).
If you want, you can send me all the files of this theme in a zipped folder so that i can test it on my domain, without going through the dashboard and see if I can come up with a solution.
Boutros.
Hi Boutros, thank you very much for the great tutorial, but it seems it doesn’t work for me…I’ve follow every single step you wrote. I’ve no idea where’s the problem. The version of WP is 3.3.1. Any idea?
Thank you very much
Andrea
Hi Andrea,
Can you tell me what WordPress theme (link) you are trying to apply the Code, and I’ll take a look.
Boutros.
Hi Boutros and thanks for the prompt reply! Here is the link of the theme I bought: http://themeforest.net/item/vulcan-minimalist-business-wordpress-theme-4/111625
Thanks again!
Andrea
Hi Andrea,
Is it the Vulcan Theme? Vulcan is a CMS with a blog in it. So My tutorial applies to the blog part.
I assumed that it was a free WP theme that I could pull up the source files and test.
To be able to help you I need the source files (php files and also css).
If you want you can email me the source files in a zipped folder (Remove the PSD files, I don’t need those) and I’ll test this theme and see what’s the problem, and I’ll let you know in a day or two.
My email is at the bottom of the ‘Guest Post’ page.
Boutros.
I want to say thank you Boutros, for all the time that you spent to help me!
Andrea
You’re Welcome Andrea, and Thank you for your donation.
Good Luck.
Boutros.
Very well written. Thanks for the information.