I work on a portfolio site where the graphic designer wants a carousel at the top of the page, above the page title and the rest of the content. When she creates a page in the backend, it looks normal (title, carousel, content) and she understands that it will look differently on the frontend (carousel, title, content).

In the shortcode days, I accomplished this by:

  1. Using a regex in the theme's content.php to find the shortcode and call do_shortcode on it. This happens before the call to the_content on the page.
    $regex = '/\[carousel[^\]]*id=[\'"](.*)[\'"]?[^\]]*\]/';

    if ( preg_match_all( $regex, $post->post_content, $matches ) )
    { echo do_shortcode($matches[0][0]); }

    the_title( '<h2 class="entry-title">', '</h2>' );
    the_content( 'Continue reading...', false );
  1. In the theme's functions.php, create a filter on the_content to remove the shortcode.
function carousel_remover( $content ) {
    if ( has_shortcode( $content, 'carousel' ) ) {
        $regex = '/\[carousel[^\]]*id=[\'"](.?)[\'"]?[^\]]*\]/';

        if ( preg_match( $regex, $content ) ) {
            // Filter the shortcode out of the_content
            $content = preg_replace( $regex, '', $content, 1);
    return $content;
add_filter( 'the_content', 'carousel_remover' );
  1. When the_content is called in content.php, the shortcode has been removed. So, the order everything is rendered becomes: shortcode, title, all the rest of the content.

The carousel plugin was recently updated with a Gutenberg block and this process doesn't work with blocks.

I added a regex to match the block code in content.php, pull out the post ID, and call do_shortcode on it. That works, and the carousel is rendered above the title.

However, removing the block code in functions.php does not work. Some log dumping shows that when the content is passed to the the_content filter, the block has already been rendered to HTML. So the browser gets carousel, title, carousel, content. I also tried removing the block in content.php but this doesn't work either:

if  ( has_block( "client/carousel" ) ) {
        $blocks = parse_blocks( $post->post_content );
        foreach ( $blocks as $block ) {
            if ( 'client/carousel' === $block['blockName'] ) {
                $num = $block['attrs']['id'];
                $regex_gutenberg = '/<!-- wp:client/carousel {"id":"(.*)"} \/-->/';
                $post->post_content = preg_replace( $regex_gutenberg, '', $post->post_content, 1 );
                echo do_shortcode("[carousel id='".$num."']");
                break; // Only do this for the first carousel block found...

The block is removed from $post->post_content, but it's still rendered when I call the_content.

Where do I hook in to remove the block before the content is rendered? Or is there perhaps an easier method to move the title down below the first carousel?

Thank in advance for the advice.

1 Answer 1


The solution is/was simple. Use a priority of 1 in the add_filter() function.

function carousel_block_remover( $content ) {
    // Matches <!-- wp:client/carousel {"id":"100"} /-->
    $regex = '/<!-- wp:client\/carousel {"id":"(.*)"} \/-->/';

    if ( preg_match( $regex, $content ) ) {
        // Filter the first block out of the_content
        $content = preg_replace( $regex, '', $content, 1);
    return $content;
add_filter( 'the_content', 'carousel_block_remover', 1 );

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.