|

Programmatically add classes to blocks in the WordPress editor based on attributes

Overview

When working with custom attributes in the WordPress block editor, you may want to add a specific CSS class to block components based on the value of your attributes.

In my example, I wanted to add the class block-visibility__is-hidden to every block that had the hideBlock attribute set to true. I could then style these blocks as needed in the editor so users could visually see which blocks were hidden.

This post will detail how adding block classes based on custom attributes can be achieved. Note that we will not be covering how to add classes to blocks on the front end of your site, just the block editor. Jump to the summary if you are just looking for the solution.

Setup

I am assuming you are familiar with JavaScript (ESNext), React and have an appropriate development environment for your project. If you are not, or need a refresher, check out the Tutorials in the Block Editor Handbook.

To add custom classes to blocks in the editor, you need to use the editor.BlockListBlock filter. More information on this filter, and block filters in general, can be found in the Block Editor Handbook.

The first thing you need to do is add the filter. All filters have the following format addFilter( 'hookName/filterName', 'namespace', callback, priority ). But, before you can actually use this function, you need to import it into your project from the @wordpress/hooks module. See below for what the end result will look like.

/**
 * WordPress dependencies
 */
import { addFilter } from '@wordpress/hooks';

addFilter(
	'editor.BlockListBlock',
	'your-plugin/your-custom-class',
	withYourCustomBlockClass
);

In this example, we don’t need to worry too much about priority, but you can add it if you need to down the line.

Next, you need to create the callback function, which will be a higher-order component of the BlockListBlock component. BlockListBlock “wraps” around every block component in the WordPress editor and applies various properties and classes. We will be using the handy createHigherOrderComponent function to accomplish this, which can be imported from the @wordpress/compose module. The initial setup without any customizations should look something like the following.

/**
 * WordPress dependencies
 */
import { addFilter } from '@wordpress/hooks';
import { createHigherOrderComponent } from '@wordpress/compose';

const withYourCustomBlockClass = createHigherOrderComponent( ( BlockListBlock ) => {
    return ( props ) => {
        return <BlockListBlock { ...props }/>;
    };
}, 'withYourCustomBlockClass' );

addFilter(
	'editor.BlockListBlock',
	'your-plugin/your-custom-class',
	withYourCustomBlockClass
);

Customizations

Now that the filter is completely setup, you can start adding the desired customizations to your withYourCustomBlockClass function.

Adding a class

To add a custom class, you simply add a className attribute to the BlockListBlock component.

const withYourCustomBlockClass = createHigherOrderComponent( ( BlockListBlock ) => {
    return ( props ) => {
        return <BlockListBlock { ...props } className={ 'your-custom-class' }/>;
    };
}, 'withYourCustomBlockClass' );

This will add your-custom-class to every block in the editor. While this is likely not the outcome you are looking for, it’s a good start.

Adding a class based on an attribute

To display the class based on an attribute, you need to retrieve the block attributes from props. Assume that the custom attribute is named customAttribute and you want to add the custom class if the attribute exists on the block, and it’s value is true. The code would look something like this.

const withYourCustomBlockClass = createHigherOrderComponent( ( BlockListBlock ) => {
    return ( props ) => {
        const { attributes } = props;
        const { customAttribute } = attributes;
        const customClass = customAttribute ? 'your-custom-class' : '';

        return <BlockListBlock { ...props } className={ customClass }/>;
    };
}, 'withYourCustomBlockClass' );

Again, this filter will target every block in the editor but will only add the class if the block has customAttribute set to true. Of course, your attributes could be much more complicated than a simple boolean, and you could apply different custom classes based on the value(s) of each attribute.

Limit the custom class to selected blocks

In the examples above, we have targeted every block type in the editor. What if you only want to add a custom class to a specific block type or a group of blocks?

The props variable contains pretty much everything you need to know about a block, including its name. Try console.log( props ); and you will see all the information that is available to you. Because of this, there’s tons of “filtering” you can do.

Assume you only want to add your-custom-class to paragraph blocks. You would then do something like the following. If the block does not have the appropriate name, you just return the unedited BlockListBlock component.

const withYourCustomBlockClass = createHigherOrderComponent( ( BlockListBlock ) => {
    return ( props ) => {
        const { name, attributes } = props;

        if ( name != 'core/paragraph' ) {
            return <BlockListBlock { ...props }/>;
        }

        const { customAttribute } = attributes;
        const customClass = customAttribute ? 'your-custom-class' : '';

        return <BlockListBlock { ...props } className={ customClass }/>;
    };
}, 'withYourCustomBlockClass' );

While this is a simple example, you can get much more sophisticated in the blocks you are filtering out. In my Block Visibility project, there is an entire function dedicated to determining which block(s) should have the block-visibility__is-hidden class.

Summary

This post gave you a quick overview of how you can add custom classes to blocks in the WordPress editor based on block attributes and also depending on the block type (name). This should give you a good starting point for your projects.

Below is the complete code for adding the CSS class your-custom-class to all paragraph blocks if the block has the custom attribute yourAttribute set to true. Of course, paragraph blocks do not naturally have this attribute, so you would need to add it for this example code to do anything useful. But that is a post for another time.

/**
 * WordPress dependencies
 */
import { addFilter } from '@wordpress/hooks';
import { createHigherOrderComponent } from '@wordpress/compose';

const withYourCustomBlockClass = createHigherOrderComponent( ( BlockListBlock ) => {
    return ( props ) => {
        const { name, attributes } = props;

        if ( name != 'core/paragraph' ) {
            return <BlockListBlock { ...props }/>;
        }
	
	const { yourAttribute } = attributes;
	const customClass = yourAttribute ? 'your-custom-class' : '';

        return <BlockListBlock { ...props } className={ customClass } />;
    };
}, 'withYourCustomBlockClass' );

addFilter(
	'editor.BlockListBlock',
	'your-plugin/your-custom-class',
	withYourCustomBlockClass
);

Latest articles