WordPress automatically generates an excerpt when none has been written manually, it takes the first 55 words of the post content, strips shortcodes and HTML, and appends a truncation indicator. The default truncation string is [...], which is a bracket-enclosed ellipsis that looks like a code artefact rather than a design choice. And 55 words is a one-size-fits-all default that may be too long or too short depending on how your theme lays out post archives and blog loops.
These two filters let you set an appropriate word count for your layout and replace the truncation indicator with a proper read more link that drives clicks to the full post.
The Code
Add this to your functions.php or a site-specific plugin. Both filters use priority 999 to ensure they override any default values set by the theme, some themes set their own excerpt length using the same filters, and running at a higher priority guarantees your values win.
Choosing the Right Word Count
The right excerpt length depends entirely on how your blog loop or archive is laid out. A three-column card grid with a small card height might only have room for 15 to 20 words before the card overflows. A single-column blog list with generous spacing might accommodate 40 to 50 words comfortably. A full-width featured post might display 25 words at a large font size.
Start with the layout you’ve designed, count the words that fit visually, and set the filter to that number. If you have multiple archive layouts with different available space, for example a featured post that shows more words and supporting posts that show fewer, you’ll need additional logic in the callback to check which template is rendering and return different values accordingly.
The Read More Link
The excerpt_more filter replaces everything that comes after the last word in the excerpt. The default [...] is a static string with no link. The snippet replaces it with an HTML ellipsis entity (…) followed by an anchor tag pointing to the full post URL. The anchor has a read-more class applied for CSS targeting, you can style it as a button, an underlined link, or with any visual treatment your theme uses for CTAs.
Manual Excerpts Take Priority
These filters only affect auto-generated excerpts, when the Excerpt field in the post editor is empty and WordPress creates the excerpt from post content. If a post has a manually written excerpt, WordPress uses that text as-is and these filters are not applied. This means posts where you’ve written a custom excerpt get exactly the text you wrote, while posts without one get the auto-generated version with your custom length and read more link.
HTML in Excerpts
Auto-generated excerpts strip all HTML from post content before truncating. Manually written excerpts preserve any HTML you type into the excerpt field. If you need formatted excerpts, bold text, inline links, write them manually per post rather than relying on auto-generation.
// Change the excerpt word count
add_filter( 'excerpt_length', function( $length ) {
return 30; // Words, adjust to suit your layout
}, 999 );
// Replace the [...] with a custom read more link
add_filter( 'excerpt_more', function( $more ) {
return sprintf(
'… <a class="read-more" href="%s">Read more</a>',
esc_url( get_permalink() )
);
}, 999 );
