I don’t know if you’ve noticed or not, but last week we updated our website and installed a new theme. Our new theme is based on WordPress’ Twenty Twenty-Three and it’s been properly modified to better suit our needs. And the good news is, this updated helped us learn more about Full Site Editing.
In this post we’ll look at a trick we’ve implemented in the theme to smart enqueue block styles. Don’t you know what I’m talking about? Keep reading and you’ll understand.
Tweak Block Styles to Suit Our Needs
Let’s start with a simple example. Our website has many testimonials in it, which we use to share the opinion our users have about our plugins. To create these testimonials comfortably, we added the following block pattern in our new theme:
Write testimonial…

Name
Position
A block pattern is, as you may already know, a predefined set of blocks that provide a certain design. For instance, our “Testimonial” block is basically a group that wraps a paragraph and a row. The row contains information of the testimonial’s author: on the one hand, a picture, and on the other hand, their name and further details organized in a column.
All design properties of this block have been designed using the block editor: typography, margins, paddings… All but one. If you pay attention, you’ll notice a quotation mark in the testimonial. We’ve added this image via CSS by adding the is-testimonial
class to the group block wrapper:
.wp-block-group.is-testimonial > p:first-child {
position: relative;
}
.wp-block-group.is-testimonial > p:first-child:before {
background: var(--wp--preset--color--tertiary);
content: "";
display: block;
font-size: 2rem;
height: 1em;
left: -1em;
-webkit-mask-image: url(data:image/svg+xml;base64,...);
mask-image: url(data:image/svg+xml;base64,...);
position: absolute;
top: -0.3em;
width: 1em;
}
And that’s the first customization tip you should be aware of: adapting WordPress blocks to our needs can be as easy as assigning them a class and defining the specific styles we want.
Classic Style Enqueuing
WordPress version 5.0 introduced a couple of actions to enqueue the block assets: enqueue_block_assets
and enqueue_block_editor_assets
. As you can read in the linked documentation, the former enqueues block assets in both the front-end and the editor, while the latter only does so in the editor.
With this in mind, if we want to enqueue the is-testimonial
style on our website, all we gotta do is:
add_action(
'enqueue_block_assets',
function() {
$filename = 'styles/testimonial.css';
wp_enqueue_style(
'nelio-testimonial',
get_stylesheet_directory_uri() . $filename,
array(),
filemtime( DIR . $filename )
);
}
);
Unfortunately, this solution is far from ideal: it enqueues the testimonial styles everywhere, regardless of a page’s content. If the current page has no testimonials, we clearly don’t need these styles. Can we do better?

Nelio Forms
A fantastic contact plugin using the block editor. In its simplicity lies the true power of this plugin. I love it, very versatile and it worked perfectly for me.

Wajari Velasquez
Smart Style Enqueuing
Smart style enqueuing is all about enqueuing the styles that are relevant to the current page. If a set of CSS does not apply to the current page, don’t include it. So, in our running example, if a page has no testimonials, we don’t want to enqueue testimonial styles. But if it does have at least one testimonial, we do.
This might sound complicated to achieve, but it’s actually pretty easy. When WordPress renders a certain block type, it runs a filter named render_block_{$blockname}
. We can use this filter to detect when WordPress is about to render a testimonial block by filtering render_block_group
and checking if the group that’s being currently rendered has the is-testimonial
class:
function add_testimonial_style( $content, $block ) {
if ( ! has_classname( 'is-testimonial', $block ) ) {
return $content;
}
ob_start();
require( DIR . 'styles/testimonial.css' );
$css = ob_get_contents();
ob_end_clean();
wp_enqueue_block_support_styles( $css );
remove_filter( 'render_block_group', 'add_testimonial_style', 10, 2 );
return $content;
}
add_filter( 'render_block_group', 'add_testimonial_style', 10, 2 );
If it does, we read the CSS rules of a testimonial and enqueue them using wp_enqueue_block_support_styles
. Once the styles have been added, there’s no need to keep filtering group renders, so we simply remove the filter.
And that’s how you smart enqueue styles in the front-end! Pretty neat, huh?
Oh and, by the way, has_classname
is a helper function we created to safely check if a block has a certain CSS class or not:
function has_classname( string $classname, array $block ): bool {
if ( empty( $block['attrs'] ) ) {
return false;
}//end if
$block = $block['attrs'];
if ( empty( $block['className'] ) ) {
return false;
}//end if
$classes = explode( ' ', $block['className'] );
return in_array( $classname, $classes, true );
}//end has_classname()
What about the editor, you ask? Well, we need to enqueue them again using the enqueue_block_editor_assets
action I mentioned earlier:
add_action(
'enqueue_block_editor_assets',
function() {
$filename = 'styles/testimonial.css';
wp_enqueue_style(
'nelio-testimonial',
get_stylesheet_directory_uri() . $filename,
array(),
filemtime( DIR . $filename )
);
}
);
Automatic Smart Style Enqueuing
The previous solution is great, but we can still do better. How? Well, right now, we have to replicate the previous steps for each block type and custom class we add. For example, our website also has a “Featured Testimonial,” which we built using a cover
block with the is-featured-testimonial
class. To load the appropriate styles, we need the following code:
function add_featured_testimonial_style( $content, $block ) {
$classes = explode( ' ', $block['attrs']['className'] );
if ( ! in_array( 'is-featured-testimonial', $classes, true ) ) {
return $content;
}
ob_start();
require( DIR . 'styles/featured-testimonial.css' );
$css = ob_get_contents();
ob_end_clean();
wp_enqueue_block_support_styles( $css );
remove_filter( 'render_block_cover', 'add_featured_testimonial_style', 10, 2 );
return $content;
}
add_filter( 'render_block_cover', 'add_featured_testimonial_style', 10, 2 );
which is basically what we already had with some minor tweaks:
- The name of the function
- The name of the filter
- The name of the class
- The name of the CSS file
We’re clearly repeating a lot of stuff here… and that’s something that bugs us. Being lovers of the DRY principle, we couldn’t miss the opportunity to remove this code duplication by abstracting a better solution. We implemented a simple, powerful, and generic solution to smart style enqueuing: just name CSS files properly and let these names guide the style enqueuing process.
For instance, in this post we’ve talked about:
- a “normal testimonial” based on a group block
- a “featured testimonial” based on a cover block
So all we gotta do is create the following CSS files:
styles/group--is-testimonial.css
styles/cover--is-featured-testimonial.css
and their names quickly tell us (a) the type of block they apply to and (b) the classname the related block should have to make this style mandatory in the front.
Now we can create a helper function like this:
function add_block_stylesheet( string $filename ): void {
$parts = explode( '--', str_replace( '.css', '', $filename ) );
$blockname = $parts[0];
$classname = isset( $parts[1] ) ? $parts[1] : '';
add_action(
'enqueue_block_editor_assets',
function() use ( $filename ): void {
$handle = array_reverse( explode( '/', $filename ) )[0];
$handle = str_replace( '.css', '', "nelio--{$handle}" );
wp_enqueue_style(
$handle,
trailingslashit( get_stylesheet_directory_uri() ) . $filename,
array(),
filemtime( DIR . $filename )
);
}
);
$enqueue_in_front = function( string $content, array $block )
use ( &$enqueue_in_front, $filename, $blockname, $classname ): string {
if ( empty( $classname ) || has_classname( $classname, $block ) ) {
ob_start();
require( DIR . $filename );
$css = ob_get_contents();
ob_end_clean();
wp_enqueue_block_support_styles( $css );
remove_filter( "render_block_{$blockname}", $enqueue_in_front, 10, 2 );
}//end if
return $content;
};
add_filter( "render_block_{$blockname}", $enqueue_in_front, 10, 2 );
}//end add_block_stylesheet()
that can parse the name of a CSS file and automatically add the required filters we previously had to define manually.
Finally, we simply loop through all our CSS files:
array_map(
'add_block_stylesheet',
array_map( 'basename', glob( DIR . 'assets/block-styles/**/*.css' ) ),
);
and voilà! We have all the required hooks in place to smart enqueue styles when needed. Fantastic!
I hope you liked today’s post and, if you did, please share it with your friends and followers. Thanks for reading us and see you in the next post!
Leave a Reply