Last updated:

Performant CSS using wp_enqueue_block_style

Writing performant CSS is key for fast loading sites. Something which both your visitors and search engines enjoy.

Block themes don’t need to enqueue the style.css file, or any other monolithic stylesheet. Instead they use Global Styles and per-block stylesheets to achieve the desired styles.

In this article, we’re going to look at how you can write CSS for specific blocks, and enqueue it in the most efficient way.

Table of Contents

Introducing wp_enqueue_block_style

The wp_enqueue_block_style function has two required arguments:

  1. $block_name: The unique identifier of the block type that you want to enqueue the stylesheet for.
  2. $args: The data to enqueue the stylesheet. Most of the arguments are the same as you know from wp_enqueue_style() or wp_register_style().

This code snippet enqueues a stylesheet for the paragraph block:

function wpdc_enqueue_paragraph_block_style() {
    wp_enqueue_block_style(
        'core/paragraph',
        [
            'handle' => 'wpdc-paragraph-style',
            'src' => get_theme_file_uri( 'assets/css/core-paragraph.css' ),
            'path' => get_theme_file_path( 'assets/css/core-paragraph.css' ),
            'deps' => [],
            'version' => 'v1',
        ]
    );
}
add_action( 'after_setup_theme', 'wpdc_enqueue_paragraph_block_style' );Code language: PHP (php)

Let’s go over the snippet.

We create our own callback function to call the scripted enqueueing function. But note the action we use: it’s after_setup_theme. We’ll look at why we use this hook in the next section.

The first function argument is the unique identifier of the block we want to add the style to. core means that it is a default WordPress block, and paragraph is the block type.

If you want to know the identifier of a block, you can add the block to the editor, and then click

The second argument is the arguments array:

  • handle is the unique identifier of the stylesheet. You should use a prefix here, in our case wpdc, as other code might enqueue a stylesheet for this block as well.
  • src is the URL to the stylesheet. We use get_theme_file_uri() to generate the URL.
  • path gives the location of the stylesheet on the filesystem. This is needed, so that WordPress can read the contents of the file (more on that later). We use get_theme_file_path() here.
  • deps is the array of handles that the script depends on. These handles need to be for registered styles, either through
  • version is a string used to clear browser caches when the stylesheet changes. It’s still recommended to use this string, even if it’s not necessary when WordPress reads the file from disk.

Dependency handling for the wp_enqueue_block_style function is different than for wp_enqueue_style. This is because the block styles are added both to the frontend and the backend of the website. Therefore the dependencies need to be registered both contexts.

There are two options here:

  1. If the dependencies are per block styles as well, use wp_enqueue_block_style as shown above.
  2. If the dependencies are global stylesheets, then enqueue them using thewp_enqueue_stylefunction, on the enqueue_block_assets hook. This will ensure that the dependency is loaded both on the frontend and in the backend.

Differences between wp_enqueue_style and wp_enqueue_block_style

But there are four key differences between the wp_enqueue_style and wp_enqueue_block_style.

First is the action to which the callback is added. While we are used to the wp_enqueue_scripts hook for enqueuing stylesheets, we use after_setup_theme for per block styles.

This is because we are not enqueuing the per block styles, we are listing them as needing to be enqueued. If this sounds confusing, don’t worry: we’ll cover this in the next section.

The second is the context in which the per block styles are added. When using wp_enqueue_block_style, the styles will be added to both the frontend, and all admin pages that do contain a block editor.

The third difference is on which pages the block styles are added. The best term I’ve come up for this is “selective CSS”. In simple terms it means that if you add a block style to a block, this style is only enqueued when the block is present on the page.

Which brings us to the fourth difference, and that is that the block style CSS might either be enqueued, or inlined.

These differences aren’t just random choices. Instead they all work together to improve the performance of your website.

How wp_enqueue_block_style enables Code Splitting

WordPress has a wp_should_load_separate_core_block_assets function, which returns the value of the should_load_separate_core_block_assets filter.

This is the toggle that WordPress uses to enable selective loading of CSS stylesheets. This technique is called code splitting. Rather than one big stylesheet loaded on every page, we use smaller ones that are only loaded when needed.

For block themes, selective CSS is the default behavior. Meaning WordPress will only load block styles for blocks that are present on the page.

But how does WordPress know which blocks are on a page?

It doesn’t. Instead it uses the render_block filter to enqueue the style. WordPress passes the HTML of the block through this filter before rendering it on the frontend. So it’s a clever way to detect whether a block actually gets rendered.

Hybrid and even Classic themes can also toggle the selective loading on. But there’s one issue here: these themes do not support Global Styles.

In a block theme, the wp_add_global_styles_for_blocks() function will take the CSS for blocks, and inline or enqueue them in the <head> section of the website. This means that when the page renders, all the styles are loaded before the HTML in the body.

In a hybrid of classic theme, separate loading will put the stylesheets in the footer. This can lead to HTML being rendered on the page without any styles, as they’ll only get loaded once the whole <body> is output. This can cause flashes of unstyled content, which is an unsettling user experience.

So, should you still use wp_enqueue_block_style()? Yes, for two reasons.

First of all it is the most future proof method for block styling. It also teaches you the right habits for efficient CSS. A lot of WordPress developers are just used to dumping everything into a big CSS file, often relying on Sass. Having to create small individual CSS files is a new experience, and something that needs getting used to.

Second is that it’s more practical to use a function that does both the frontend, and the backend enqueuing for you. Of course you could just handle that yourself, but I find that any simplification of the development process is welcome.

This flow diagram explains how WordPress decides on the hook to use for enqueuing:

Diagram that explains how wp_enqueue_block_style decides on the action or filter to use to enqueue styles: render_block, wp_footer, or wp_enqueue_scripts

How wp_enqueue_block_style enables Critical CSS

Even in web design, we still use the word “above the fold”. This term refers to newspapers, that are sold folded in the middle. Prospective buyers can only see what is above the fold of the first page. So that part of the paper is optimized to attract a maximum of attention.

We use the term to refer to the immediately visible part of a website. So anything a users sees without scrolling. This content should be visible as soon as possible.

The idea behind critical CSS is to identify which CSS is needed for that top part of a website, This is then loaded first, while the rest is loaded later.

WordPress does this through its use of inlined CSS in the <head> section of the website. Any styles defined through Global Styles, and generated from the theme.json file, are placed in there.

But your per block stylesheets are also added in there–up to a point. You cannot put all CSS into the head section, so there is an upper limit to the size here.

So what WordPress does is it pre-renders the blocks when a block-based page is loaded. And as blocks are rendered in their order of appearance, this enables to inline the CSS of the blocks that are visible first.

Conclusion

Part of the reason why like block themes so much is that they are performant by default.

And thanks to tools like the wp_enqueue_block_style function, I can focus on the process of building websites. Without having to fidget with details of what stylesheet to add where and when. WordPress will take care of this for you.

But even if you are maintaining hybrid or classic themes, I would recommend that you adopt some of these approaches. While you won’t get all of the performance benefits, you’ll still practice building in a more modern way.

Fränk Klein Avatar