Supporting Multiple “Block Styles” in the WordPress Block Editor

I’ve been talking about block styles a lot lately, and I’ve got more to say!

Block Styles are Super Useful

Editing a web page should be as easy as possible. That sounds obvious, but it requires real thought, attention, and experimentation to find the best ways of guiding and empowering site editors.

The WordPress Block Editor has made editing much easier in many ways by providing tools that instantly show editors the impact of their choices. Block Styles is among my favorite of these tools.

WordPress block editor containing a list block. The block have 5 available styles in the editing sidebar: Default, Unstyles, Circle Numbers, Multicolumn, and No Markers.
A basic example of block styles. Here, a list can be styled in multiple ways including special numbering, in multiple columns, or without list markers. This is a combination of custom theme styles and a some of the styles in the Useful Block Styles plugin I’ve been building.

With just a few lines of PHP code, I can define a new Block Style and then use CSS style it. It is fast, powerful, and user-friendly.

register_block_style(
	'core/list',
	array(
		'name'  => 'useful-multicolumn',
		'label' => 'Multicolumn',
	)
);

However, there is one huge limitation of Block Styles. You can only select one style per block.

Many folks have requested the ability to use multiple block styles together, myself included, but that’s a potentially complicated request. It’s complicated because one can’t assume every Block Style can be combined with every other one, and letting editors configure incompatible design options isn’t a very good experience. For more background, read the overview of reasons for and against supporting multiple Block Styles in “Should Users Be Able To Select More Than One Block Style?” on WP Tavern.

A Perfect Use-case for Multiple Block Styles

I was recently building a site with an absolutely beautiful brand that included masked images with colorful paint strokes behind them.

WordPress editor with title Beautiful Styled Image. Image of two people holding hands appears in a paintbrush pattern with red, orange, and brown paintstrokes behind the image.

The moment I saw this design element, my mind went straight to block styles and the one-style-per-block shortcoming. Ideally, I wanted to let users combine a choice of image masks AND brush stroke design. If I provided 5 masks and 5 brush patterns, editors could make 25 unique combinations for any photo they added to the site.

I had run into almost this exact issue before, and I did not want to use the same workaround of providing 25 block styles—one per unique combo—again. The list gets long, and it’s hard to experiment with that many options.

Implementing My Own Second Block Styles Interface

Since I’ve been looking for ways to learn more about customizing the Block Editor, this new need was my chance to dive in deep and try to provide the best possible editing experience. With big kudos to “A Crash Course in WordPress Block Filters” on CSS-Tricks, I added a new set of options to the block sidebar that let editors make their own combinations of masks (with Block Styles) and brush strokes (with a new custom option).

WordPress editor showing block styles with image mask options and radio buttons to control paintstroke designs

I next wanted to make the custom options more visual like block styles, so that editors could see their choices rather than read a description of them. I added some CSS to make each radio button in the brush stroke option show the stroke it would apply.

WordPress editor showing block styles with image mask options and buttons with previews of control paintstroke designs

This gets me really close to having two sets of block styles that can be combined! I think the editors are going to love it, and I’m proud to have built it and be able to share this with others. (Yay open source knowledge.)

Here’s what it looks like in action!

But that doesn’t mean there isn’t…

Room For Improvement

Both the image masks and brush strokes use about the same amount of CSS to style the images. However, the amount of code required to create the two options panels is WILDLY different.

The image masking block style was registered in 12 lines of PHP like this:

/* Images */
$blocks_with_masks = [ 'image', 'media-text', 'cover' ];
foreach( $blocks_with_masks as $block ) {
	for( $i = 1; $i < 6; $i++ ) {
		register_block_style(
			"core/{$block}",
			[
				'name' => 'mask-' . $i,
				'label' => esc_html__( sprintf( 'Cutout #%d', $i ), 'collective' )
			]
		);
	}
}

That’s slightly more complicated than a normal single block style, but it says: For the Image, Media & Text, and Cover blocks, create 5 mask styles called “Cutout {1-5}”.

The brush stroke options, on the other hand, required ~150 lines of JavaScript, ~50 lines of PHP, and a stand-alone build process all stored in a custom plugin. Even if building this wasn’t a learning experience, the difference in time required to code each would still have been measured in multiples. And even then, the interface for selecting the brush strokes is still inferior since it doesn’t include real live preview incorporating an image with the brush stroke options applied, something that Block Styles does automatically.

Proposal for Improving the Block Styles API

So after having gone down this path and considered the arguments for and against multiple Block Styles, I’m still in favor of making it possible, because the alternative is so much more time consuming. However, I do see the need to to let developers define which styles can be combined.

Based on my own experiences using them, I think the best path forward is:

  1. Introduce a new concept of “Block Style Categories”
  2. Only allow an editor to select of one Block Style per Block Style Category

(I see I’m not the first to suggest this either.)

Since Block Patterns already have a similar concept of categories, using the same API pattern would make sense:

/* this function does not exist, only a proposal */
register_block_style_category(
	'my-style-category',
	array( 'label' => __( 'My Style Category', 'mytextdomain' ) ),
);

/* this is a real function, but 'category' attribute is just a proposed */
register_block_style(
	'core/list,
	[
		'name' => 'my-style',
		'label' => __( 'My Style', 'mytextdomain' ),
		'category' => 'my-style-category' // optional! defaults to a general category
	]
);

A new register_block_style_category function and a category argument for register_block_style would be the only new additions to existing APIs. From there, the Block Editor would ensure that content editors can only ever select one style per category and that every style gets a live preview of the block.

Block Styles are the Future. Let’s Make them Awesome-r.

As Kjell Reigstad showed in his presentation at WordCamp US 2021, Block Styles provide an amazing way to give editors the power to build really creative designs. A single CSS class can trigger wildly complex and interesting visual changes to text formatting, image styling, and even animations.

The future of WordPress theming will require less and less custom CSS written by theme developers, but I think Block Styles will remain an exception to that rule. Block Styles make possible things that a content editor could never create with existing options.

In another talk at WCUS, Helen Hou-Sandí encouraged everyone in the WordPress community to keep pushing the limits of the block editor and imagine how it could be better for both editors and developers. That’s the true spirit of open source software, and I hope I’m living up to the call with this post and my involvement in feature requests like this one in the Gutenberg repository.

I think it’s worth improving the Block Styles feature, and I think this is how to do it.

3 thoughts on “Supporting Multiple “Block Styles” in the WordPress Block Editor”

  1. Hello, your article is very interesting !
    I saw your message on github and I hope your proposal will be accepted and developped 😁
    But as the discussion started in 2019 I don’t have much hope that it will be fast.
    I was about to ask you where to find an example of your workaround method, but I realized adding a plugin and a big js file won’t be the solution I need, a bit complicated for me.
    Instead of creating one array $blocks_with_masks, What do you think of creating an array for each styles group, and creating a function that will loop all arrays to create our unique combinations ?

    1. @classikd Glad you found the article useful. I really would recommend a custom option if you’re going to have more than 15 or 20 styles. That said, The solution I had used in the past was what you describe. Loop through all of Style 1 and loop through all of Style 2 within that loop, creating each combination. It definitely works, but the result is _a lot_ for editors to take in, and I suspect that the styles far down the list don’t get much use. (So considering that, try to get the best options first in each loop.)

  2. Indeed you are right with a lot of styles it would be a big mess. So this is a not a solution… 🤐
    I am definetly going to take a look at the csstricks article you mentionned !

Join the Discussion

This site uses Akismet to reduce spam. Learn how your comment data is processed.