How to Build a Gutenberg Block with Custom Styles

In this tutorial, we will learn how to add block-specific styles to a Gutenberg block. We will be loading two separate CSS files. The first (style.css) will be applied to both the frontend and the editor. The second (editor.css) will only be applied within the Gutenberg editor.

This tutorial builds off the How to Build Gutenberg Blocks Using JSX tutorial. If you’re not familiar with Gutenberg or JSX, I would suggest starting with that tutorial.

The code from this tutorial is available as a fully functioning plugin. Check out the example on Github.

PHP

The main plugin PHP file defines the plugin details and loads our Javascript and CSS files. It doesn’t have any significant differences from the How to Build Gutenberg Blocks Using JSX example that this tutorial is based on.

<?php
/**
 * Plugin Name: Gutenberg Block: Block Styles - JSX Example
 * Plugin URI: https://github.com/modularwp/gutenberg-block-styles-jsx-example
 * Description: An example Gutenberg block with custom CSS file. Built with JSX/ES6.
 * Author: ModularWP
 * Author URI: https://modularwp.com/
 * Version: 1.0.0
 * License: GPL2+
 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
 */

defined( 'ABSPATH' ) || exit;

/**
 * Enqueue the block's assets for the editor.
 *
 * Javascript dependencies:
 * wp-blocks:  The registerBlockType() function to register blocks.
 * wp-element: The wp.element.createElement() function to create elements.
 * wp-i18n:    The __() function for internationalization.
 *
 * CSS dependencies:
 * wp-blocks: The WordPress core block styles.
 *
 * @since 1.0.0
 */
function mdlr_block_style_jsx_example_backend_enqueue() {
	wp_enqueue_script(
		'mdlr-block-style-jsx-example-backend-script', // Unique handle.
		plugins_url( 'js/block.build.js', __FILE__ ), // block.js: We register the block here.
		array( 'wp-blocks', 'wp-i18n', 'wp-element' ) // Dependencies, defined above.
	);

	wp_enqueue_style(
		'mdlr-block-style-jsx-example-style-editor', // Unique handle.
		plugins_url( 'css/editor.css', __FILE__ ), // editor.css: This file styles the block in the editor.
		array( 'wp-blocks' ), // Dependencies, defined above.
		filemtime( plugin_dir_path( __FILE__ ) . 'css/editor.css' ) // Version: filemtime - Gets file modification time.
	);
}
add_action( 'enqueue_block_editor_assets', 'mdlr_block_style_jsx_example_backend_enqueue' );

/**
 * Enqueue the block's assets.
 *
 * It should be noted that this hook fires on both the frontend
 * and the backend.
 *
 * CSS dependencies:
 * wp-blocks: The WordPress core block styles.
 *
 * @since 1.0.0
 */
function mdlr_block_style_jsx_example_enqueue() {
	wp_enqueue_style(
		'mdlr-block-style-jsx-example-style', // Unique handle.
		plugins_url( 'css/style.css', __FILE__ ), // style.css: This file styles the block both in the editor and on the frontend.
		array( 'wp-blocks' ), // Dependencies, defined above.
		filemtime( plugin_dir_path( __FILE__ ) . 'css/style.css' ) // Version: filemtime - Gets file modification time.
	);
}
add_action( 'enqueue_block_assets', 'mdlr_block_style_jsx_example_enqueue' );

This code is pretty standard for enqueueing scripts and styles. There are just a couple things to notice before moving on. First, we are adding actions to multiple action hooks:

  • enqueue_block_editor_assets – This hook only fires on the backend. We use it to load both the block.js file for our block, and the editor.css file with our editor specific styles.
  • enqueue_block_assets –  This hook fires on both the frontend and the backed, so we use it to load the style.css file that holds our base styles.

Second, notice that our CSS files list wp-blocks as a dependency. This dependency holds the default block styles provided by Gutenberg.

Javascript

All the Javascript for our plugin will be placed in the js/block.js file and will be compiled to the js.block.build.js file. This file is almost the same as the block.js file in the How to Build Gutenberg Blocks Using JSX tutorial. The only real difference is that now we’re using a class name so that we can use CSS to style our block.

const { __ } = wp.i18n;
const { registerBlockType } = wp.blocks;

registerBlockType( 'mdlr/styles-jsx-example', {
	title: __( 'Block Styles JSX Example' ),
	icon: 'admin-appearance',
	category: 'common',
	edit( { className } ) {
		return (
			<div className={ className }>Block with styles. Built with JSX.</div>
		);
	},
	save( { className } ) {
		return (
			<div className={ className }>Block with styles. Built with JSX.</div>
		);
	},
} );

CSS

Now we can create our two CSS files that will style our new block. First, the style.css file with styles that will be applied to both the frontend and the editor.

.wp-block-mdlr-styles-jsx-example {
	background-color: #333333;
	color: #ffffff;
	padding: 2em 3em;
}

Second, the editor.css file with styles that are only applied within the editor.

.wp-block-mdlr-styles-jsx-example {
	border-left: 15px solid #000000;
}

The class name is automatically generated by Gutenberg, using the namespace and block name from the registerBlockType call. The syntax is:

wp-block-{namespace}-{block-name}

So since we used mdlr/styles-jsx-example as the namespace/block name of our block, our auto-generated class name is wp-block-mdlr-styles-jsx-example.

Conclusion

Now we should have a darkly styled block on the frontend:

Block styles frontend

…and a similarly styled block on the backend, with the addition of a border on the left:

Block styles backend

If you have any questions about this tutorial or Gutenberg in general, feel free to comment below or contact me on twitter.