Block-styles loading enhancements in WordPress 5.8

WordPress 5.8 improves the way we load blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience.-styles by introducing 2 new features:

  • Load styles only for rendered blocks in a page
  • Inline small styles

Only load styles for used blocks

This is an opt-in, non-breaking change. Using the should_load_separate_core_block_assets filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output., developers can opt-in to this feature:

add_filter( 'should_load_separate_core_block_assets', '__return_true' );

Prior to WordPress 5.8, styles for all blocks were included in a style.css file that gets loaded on every page. By opting-in to separate styles loading, the following will happen:

  • The wp-block-library stylesheet changes: Instead of loading the wp-includes/css/dist/block-library/style.css file which contains all styles for all blocks, this handle will now load the (much smaller) wp-includes/css/dist/block-library/common.css file, which contains generic styles like the default colors definitions, basic styles for text alignments, and styles for the .screen-reader-text class.
  • Styles for blocks will only get enqueued when the block gets rendered on a page.

The above changes will only apply to the frontend of a site, so all editor styles will continue to work as they did before.

The difference between block themes and classic themes

Block themes

In a block theme, blocks get parsed before the <head> so we always know which blocks will be present prior to rendering a page. This makes it possible to add the block styles to the <head> of our document.

Classic themes

In a classic, php-based theme, when a page starts to render, WordPress is not aware which blocks exist on a page and which don’t. Blocks gets parsed on render, and what that means is that block-styles don’t get added in the <head> of the page. Instead, they are added to the footer, when print_late_styles() runs.

If you have an existing theme and you want to opt-in to this improvement, you will need to test your theme for style priorities. Opting-in to separate styles loading in a classic theme means that the loading order of styles changes. Block styles that used to be in the head will move to the footer, so you will need to check your theme’s styles and make sure any opinionated styles you add to blocks have a higher priority than coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. styles.

Taking advantage of separate styles loading to add pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party/theme styles to blocks

It is possible to use this new feature to attach styles to existing block-styles, by inlining them.

If your theme adds styles to blocks, instead of loading a single file containing all styles for all blocks, you can split styles and have a single file per-block. This will allow you to only load your theme’s (or plugin’s) block styles only when a block exists on a page.

The function below is an example implementation of how to do that, with some additional tweaks:

  • It works both in WordPress 5.8 and previous versions
  • It has a fallback in case the should_load_separate_core_block_assets filter is disabled
  • It adds styles both in the editor and frontend
  • Checks for specific editor block styles.

Feel free to use this as an example, tweaking it to suit your needs and implementation.

/**
 * Attach extra styles to multiple blocks.
 */
function my_theme_enqueue_block_styles() {
	// An array of blocks.
	$styled_blocks = [ 'paragraph', 'code', 'cover', 'group' ];

	foreach ( $styled_blocks as $block_name ) {
		// Get the stylesheet handle. This is backwards-compatible and checks the
		// availability of the `wp_should_load_separate_core_block_assets` function,
		// and whether we want to load separate styles per-block or not.
		$handle = (
			function_exists( 'wp_should_load_separate_core_block_assets' ) &&
			wp_should_load_separate_core_block_assets()
		) ? "wp-block-$block_name" : 'wp-block-library';

		// Get the styles.
		$styles = file_get_contents( get_theme_file_path( "styles/blocks/$block_name.min.css" ) );

		// Add frontend styles.
		wp_add_inline_style( $handle, $styles );

		// Add editor styles.
		add_editor_style( "styles/blocks/$block_name.min.css" );
		if ( file_exists( get_theme_file_path( "styles/blocks/$block_name-editor.min.css" ) ) ) {
			add_editor_style( "styles/blocks/$block_name-editor.min.css" );
		}
	}
}
// Add frontend styles.
add_action( 'wp_enqueue_scripts', 'my_theme_enqueue_block_styles' );
// Add editor styles.
add_action( 'admin_init', 'my_theme_enqueue_block_styles' );

Inlining small assets

In some cases small stylesheets get loaded on WordPress sites. These stylesheets require the browser to make an additional request to get an asset, and while they benefit from caching, their small size doesn’t justify that extra request, and performance would improve if they were inlined.

To that end, an inlining mechanism was implemented. This is an opt-in feature, and can be handled on a per-stylesheet basis. Internally, only assets that have data for path defined get processed, so to opt-in, a stylesheet can add something like this:

wp_style_add_data( $style_handle, 'path', $file_path );

When a page gets rendered, stylesheets that have opted-in to get inlined get added to an array. Their size is retrieved using a filesize call (which is why the path data is necessary), and the array is then ordered by ascending size (smaller to larger stylesheet). We then start inlining these assets by going from smallest to largest, until a 20kb limit is reached.

A filter is available to change that limit to another value, and can also be used to completely disable inlining.

To completely disable small styles inlining:

add_filter( 'styles_inline_size_limit', '__return_zero' );

To change the total inlined styles limit to 50kb:

add_filter( 'styles_inline_size_limit', function() {
	return 50000; // Size in bytes.
});

Inlining these styles happens by changing the src of the style to false, and then adding its contents as inline data. This way we avoid backwards-compatibility issues in themes and any additional styles attached to these stylesheets using wp_add_inline_style will still be printed.

Please note that if a stylesheet opts-in to get inlined, that is no guarantee that it will get inlined.

If for example on a page there are 30 stylesheets that are 1kb each, and they all opt-in to be inlined, then only 20 of them will be converted from <link rel="stylesheet"/> to <style> elements. When the 20th stylesheet gets inlined the 20kb limit is reached and the inlining process stops. The remaining 10 stylesheets will continue functioning like before and remain <link> elements.

If your theme opts-in to the separate block-styles, core block styles by default have path defined so they can all be inlined.

Props @sergeybiryukov for proofreading this dev-note.

#5-8, #dev-notes