WordPress Block Styles and Variations

Variations of stylish boots

When you’re building a WordPress block theme, you’ll often want to customize how a core block looks beyond what the block editor allows. Maybe you want a cover block with diagonal clip-path edges, a featured image that scales on hover, or a fancy Heading style. Before you add a class to that block, consider using a Block Style Variation.

Benefits of block style variations

While we could add a class to a block’s “Advanced” settings and style that class under “Advanced CSS” or in a stylesheet, this requires content creators (and you) to remember your class name and how to use it. Block Style Variations are a big improvement, allowing site editors to choose and apply options visually from the block editor’s controls while keeping those styles performant and flexible.

As a web designer or theme creator, making design decisions easier for site editors is a good thing. Using block style variations also means you can load CSS conditionally (only when the block exists), a performance win.

How to register styles

JavaScript, PHP, or JSON

Styles not shown
Fig. 1: Block styles aren’t reflected in visual controls.

I’ll skip the JavaScript (not my job) and look at the PHP and JSON methods.

Block Variations can be registered via PHP within the theme or in a plugin. If portability of block variations is important to you or if you need to make sure that your block styles are independent from the theme (which could be changed), a plugin approach1 is best.

Block Styles don’t require registration. They are picked up by WordPress auto-magically when you include the JSON file in your theme’s /styles/ directory.

One downside with block variations and block styles is that settings don’t appear in the block controls (see Fig. 1).

If I select a style, like the Button style variation “Outline” – that style change is not reflected in the element style controls2 in the editor even though the attributes exist.

Wait, aren’t block variations and block styles sort of the same?

When should I create a block variation vs. a block style? The answer is almost always the same as the answer to another question: Can these changes be made through theme.json styles or CSS? If (theme.json), you should almost always create a custom block style (JSON).

Block Variations, via WordPress Developer Resources, Theme Handbook

Block Variations and Block Styles are sort of the same, but also a little bit different. Naming things is hard.

Consider the problem you are solving: if theme.json supports most of what you want to accomplish and/or if you want a style to be available to more than one core block, the JSON method might work best.

Carolina Nymark notes that if you want to register Block Styles with a JSON file, “this feature requires WordPress 6.6 and version 3 of theme.json.”

If you need to do things that mostly aren’t supported in theme.json, like add interactivity with JavaScript or use a lot of custom CSS, use the JavaScript or PHP method to register your block variations.

Registering block variations with PHP

Registering block variations3 in your functions.php file makes them available in the block editor’s style panel.

My example registers four clip-path variations for the Cover block and a scale-on-hover effect for both Cover and Featured Image blocks.

/**
 * Register block style variations
 */
function mytheme_register_block_styles() {
    $cover_styles = array(
        'right-clip'     => __( 'Right Clip', 'mytheme' ),
        'bottom-clip'    => __( 'Bottom Clip', 'mytheme' ),
        'left-clip'      => __( 'Left Clip', 'mytheme' ),
        'top-clip'       => __( 'Top Clip', 'mytheme' ),
        'scale-on-hover' => __( 'Scale on Hover', 'mytheme' ),
    );

    foreach ( $cover_styles as $name => $label ) {
        register_block_style(
            'core/cover',
            array(
                'name'  => $name,
                'label' => $label,
            )
        );
    }
    
    // Featured image variation
    register_block_style(
        'core/post-featured-image',
        array(
            'name'  => 'scale-on-hover',
            'label' => __( 'Scale on Hover', 'mytheme' ),
        )
    );
}
add_action( 'init', 'mytheme_register_block_styles' );

The first function is plural, I’m registering several block styles for core/cover at once. I also want to add the “scale-on-hover” variation for the Post Featured Image block and the Cover block.

Even though I want to use the same style, “scale-on-hover”, for two core blocks – they have to be registered separately in PHP. If I was using the JSON method, I could make a style variation available across blocks using the blockTypes property.

Both of these block variations use CSS (clip-path, transition, transform) that isn’t supported in theme.json and would require some pretty long CSS strings so the PHP function seems the best approach.

Organizing CSS files

Create a /blocks/ directory in your theme to keep blocks and variation styles organized. For this example:

  • assets/css/blocks/cover-variations.css
  • assets/css/blocks/featured-image-variations.css

You can call the css files anything you want. We’ll reference this file name in the next section when we enqueue our block css.

TIP: If you just need to add a smidge of CSS (a few lines), you can include the styles directly in the register_block_style() function using the inline_style parameter. There’s a great tutorial by Mike McAlister on Ollie.com that shows you how to do this. Brian Coords has a similar example adding a checkmark variation to the ul element where registering the block style is a separate utility plugin.

I’ve decided that grouping related variations in a single CSS file makes sense and is more maintainable (for me) but you can also break your styles down into separate stylesheets for each variation, even for the same block.

Block variations and conditional CSS loading

This function conditionally enqueues your block variation stylesheets using WordPress’s wp_enqueue_block_style() function, which loads CSS only when the associated block variation is present on the page:

/**
 * Conditionally load block style CSS
 */
function mytheme_register_block_style_variations() {
    wp_enqueue_block_style( 'core/cover', array(
        'handle' => 'mytheme-cover-variations',
        'src'    => get_theme_file_uri( 'assets/css/blocks/cover-variations.css' ),
        'path'   => get_theme_file_path( 'assets/css/blocks/cover-variations.css' ),
    ));
    
    wp_enqueue_block_style( 'core/post-featured-image', array(
        'handle' => 'mytheme-featured-image-variations',
        'src'    => get_theme_file_uri( 'assets/css/blocks/featured-image-variations.css' ),
        'path'   => get_theme_file_path( 'assets/css/blocks/featured-image-variations.css' ),
    ));
}
add_action( 'after_setup_theme', 'mytheme_register_block_style_variations' );

Use the after_setup_theme to register your Block Variation stylesheets. This makes styles available on the frontend and in the editor.

Writing the CSS

In our cover-variations.css file:

.is-style-right-clip {
    /* Your clip-path styles */
}

.is-style-bottom-clip {
    /* Your clip-path styles */
}

.is-style-left-clip {
    /* Your clip-path styles */
}

.is-style-top-clip {
    /* Your clip-path styles */
}

.is-style-scale-on-hover .wp-block-cover__image-background {
    transition: transform 0.5s ease;
}

.is-style-scale-on-hover:hover .wp-block-cover__image-background {
    transform: scale(1.1);
}

In our featured-image-variations.css file:

.is-style-scale-on-hover img {
    transition: transform 0.5s ease;
}

.is-style-scale-on-hover:hover img {
    transform: scale(1.1);
}

Combining multiple related variations in one CSS file (like my four clip-path variations for the Cover block) will mean that WordPress loads the entire file if any of those variations appear on the page even though they’re not actively used. But this is still a small file and performance impact should be minimal. This is kind of a personal choice, since all of these styles are for the Cover block variations, I don’t mind keeping them together.

Another way: block styles in JSON

Originally, /styles/ was used to define Global Style Variations for themes (like a light and dark mode). An advantage of this method is that JSON files within the /styles/ directory are auto-discovered by WordPress (as of 6.0), work across the blocks you specify, and don’t require a PHP function or JavaScript. For this to work:

“You have to place each custom block style in its own JSON file, or WordPress can not parse them correctly. Place the JSON file inside a folder in your theme called styles, or a subfolder to styles (ex. /styles/blocks/custom-style.json).”

FullSiteEditing.com, Registering Block Styles using JSON

If you have a simple block style, like a fancy, visual heading that uses a special font, this could be a good reason to use JSON. You can also tell WordPress that this style can apply to different blockTypes.

{
  "$schema": "https://schemas.wp.org/wp/6.9/theme.json",
  "version": 3,
  "title": "Shadow Pop",
  "slug": "shadow-pop",
  "blockTypes": ["core/heading", "core/paragraph"],
  "styles": {
    "typography": {
      "fontFamily": "var:preset|font-family|abril-fatface",
      "fontSize": "var:preset|font-size|x-large"
    },
    "css": "text-shadow: -1px 1px 0px #fff, -2px 2px 0px var(--wp--preset--color--secondary);"
  }
}

Call this file anything you want, place it in your theme’s /styles/ directory (or a sub-dir of styles) and your style will be available in the editor:

Block Style Variations,wordpress block style variations
Magic! The core heading block now has a style variation, “Shadow Pop”.

How WordPress applies block styles

When you select a style variation in the block editor, WordPress adds a class to the block in the format .is-style-{variation-name}. For example, selecting the “Right Clip” variation on a Cover block produces this HTML:

<div class="wp-block-cover is-style-right-clip">
    <!-- Cover block content -->
</div>

You could use the full block class combined with the variation class (EX: .wp-block-cover.is-style-right-clip) but that’s probably only necessary if you actually run into specificity issues (which is unlikely, I think…).

WordPress detects your new class on the page and loads the associated stylesheet. If the page doesn’t use any of your style variations, that CSS file isn’t needed and doesn’t load.

Try block variations and block styles in your theme today!

Whether you register your block styles via PHP or through the Global Styles, you enhance your WordPress block theme in several ways:

  • Your theme stays lean because variation styles are broken down into small, load-as-needed files rather than one comprehensive stylesheet.
  • Pages now load faster since browsers only download that CSS when blocks are actually present on the page.
  • Users are happy because they can make effortless design changes without being afraid of doing it wrong.

Maintaining style variations will also be easier for you than remembering where you slapped those ad-hoc classes, wondering if they are still in use, and writing CSS in an external stylesheet or in the dreaded “Advanced CSS” panel.


Footnotes

Also see: How to Use Block Variations in WordPress which addresses InnerBlocks.

Watch on Learn.WordPress.org: Block Style Variations, Intermediate

  1. Register Block Styles via Plugin ↩︎
  2. Known issue, reflect inherited global style values ↩︎
  3. Block Styles in the Block Editor Handbook ↩︎

About the author