Limit the_excerpt with max of x characters

What I’m trying to do:
I want to display the_excerpt, but I have a maximum of x characters the_excerpt may use, but I don’t want to display a couple of characters of a word, only whole words.

Some more information:
This code is on a non-single/non-permalink web page such as archives, categories, front page, and searches, that makes me unable to use <!--more-->.

Read More

The code:
This is the code I use:

add_filter( 'excerpt_length', function( ) {
    return 20;
} );

if ( have_posts() ):
    while( have_posts() ): the_post();
        the_excerpt( );
    endwhile;
endif;

Related posts

Leave a Reply

2 comments

  1. add_filter('wp_trim_excerpt', function($text){    
       $max_length = 140;
    
       if(mb_strlen($text, 'UTF-8') > $max_length){
         $split_pos = mb_strpos(wordwrap($text, $max_length), "n", 0, 'UTF-8');
         $text = mb_substr($text, 0, $split_pos, 'UTF-8');
       }
    
       return $text;
    });
    

    This should take into account your max length and split the text at the nearest word boundary.
    Apply the filter, and call the_excerpt(); in your templates


    Apparently there’s a wp_trim_words function from WP 3.3 that you can also use, but from the source looks very inefficient. Appart from using 3 regexes, it splits the text into an array of words, and this can get very slow and memory exhaustive for large chunks of text…

  2. After some puzzling, I found this solution:

    $limit_characters = 120;
    
    function new_excerpt_length( ) {
        global $length;
        return $length;
    }
    
    function get_the_excerpt_special( ) {
        global $limit_characters, $length;
    
        if(strlen( get_the_excerpt() ) > $limit_characters ) {
            $length--;
            return get_the_excerpt_special();
        } else {
            the_excerpt();
        }
    }
    
    if ( have_posts() ):
        while( have_posts() ): the_post();
            add_filter( 'excerpt_length', 'new_excerpt_length' );
    
            $length = 20;
            get_the_excerpt_special( );
    
            remove_filter( 'excerpt_length', 'new_excerpt_length' );
    
        endwhile;
    endif;
    

    It works! YAY! But since it has to repeatably call get_the_excerpt, the page slows down a bit.