How to Create Custom Block Styles (Advanced Way)

One way to patch Gutenberg's lack of features is to use custom block styles. But most themes are not utilizing it properly. We will learn the proper way here.

Gutenberg at its core lacks features, but its simplicity is second to none compared to other WordPress page builders.

One way to cover that flaw is by utilizing custom block styles. This is powerful and easy to implement, yet most themes are not using this properly.

In this tutorial, we will cover how to create custom block styles and showcase how it can be used for a more complex design.

Step 1 – List What You Need

For example, we need to replicate this design:

According to that, let’s break down what Gutenberg doesn’t have yet:

  1. Media & Text block but with a square background behind the image.
  2. Heading block with five-stars decoration.
  3. Button block with only border and arrow pointing to the right.

So we need 3 custom styles, let’s register them.

Step 2 – Register Custom Styles

The code to add them is quite simple:

add_action( 'after_setup_theme', 'my_register_block_styles' );

function my_register_block_styles() {
  register_block_style( 'core/media-text', [
    'name' => 'half-bg',
    'label' => __( 'Half Background' ),
  ] );
  register_block_style( 'core/heading', [
    'name' => 'stars',
    'label' => __( 'Stars' ),
  ] );

  register_block_style( 'core/button', [
    'name' => 'outline-arrow',
    'label' => __( 'Outline Arrow' ),
  ] );

Now when you create the respective block, you will see the Styles option on Sidebar:

Gutenberg’s style option

Step 3 – Output Color Palette into CSS Variables

When we select a color in Gutenberg, it will apply extra classes to the wrapper. If the color name is accent, then it will add has-accent-background-color class.

How they handle that class name is up to the theme. Most of them do it like this:

.has-accent-background-color {
  background-color: #cd2653;

.has-accent-color {
  color: #cd2653;

The problem with the above is that the color is locked to that property. You can’t use it for something else like a border or in a :before pseudoselector.

It’s much more flexible if you output it as CSS Variables instead:

.has-accent-background-color {
  --bgColor: #cd2653;

.has-accent-color {
  --textColor: #cd2653;

To output those classes automatically, use the snippet below. It will read the colors defined in editor-color-palette and echo it inside <head>:

add_action( 'wp_head', 'my_output_gutenberg_palette' );
add_action( 'admin_head', 'my_output_gutenberg_palette' );

function my_output_gutenberg_palette() {
  // abort if in Admin but not inside Gutenberg editor
  if( is_admin() ) {
    global $current_screen;
    $in_editor = method_exists($current_screen, 'is_block_editor') &&
    if( !$in_editor ) { return; }

  $palette = get_theme_support( 'editor-color-palette' );
  if( !$palette ) { return; } // abort if no palette
  // format styles
  $styles = ":root .has-background { background-color: var(--bgColor); }
  :root .has-text-color { color: var(--textColor); } ";

  foreach( $palette[0] as $name => $value ) {
    $slug = $value['slug'];
    $color = $value['color'];

    $styles .= ".has-{$slug}-background-color { --bgColor: {$color}; } ";
    $styles .= ".has-{$slug}-color { --textColor: {$color}; } ";

  echo "<style> $styles </style>";

With those variables ready, we can re-purpose the color such as using Heading’s background as the star’s color instead:

.is-style-stars {
  background-color: transparent !important;

.is-style-stars::before {
  content: "★★★★★";
  color: var(--bgColor);

Step 4 – Write CSS for Admin

One important tip for this is to be lazy. No need to perfectly match the design, as long as it has resemblance, it’s fine.

Also no need to factor in mobile responsiveness because the admin most likely uses a PC to edit the site anyway.

Now that we have the right mindset, here’s how to enqueue the CSS to Gutenberg:

add_action( 'enqueue_block_editor_assets', 'my_editor_assets', 100 );

function my_editor_assets() {
  $css_dir = get_stylesheet_directory_uri() . '/css';
  wp_enqueue_style( 'my-editor', $css_dir . '/my-editor.css',
    [ 'wp-edit-blocks' ], '' );
The editor view of our new section.
This will look different depending on the theme.

Step 5 – Write CSS for Frontend

This is where we should focus our effort in.

Start by copy-pasting the admin CSS. Then tune it according to the theme and finally add mobile responsiveness.

We can put this custom styling in existing CSS or create new one like below:

add_action( 'wp_enqueue_scripts', 'my_frontend_assets', 99 );

function my_frontend_assets() {
  $css_dir = get_stylesheet_directory_uri() . '/css';

  wp_enqueue_style( 'my-style', $css_dir . '/my-style.css', [] );


You might get intimidated by how long the process for creating just 1 section. But remember that Step 3 and the enqueue process are one-time-only.

Once you learn once, it won’t take long. You’ll also be surprised at how seamless it is to convert the admin CSS into the frontend.

If you have any question regarding Custom Block Style, feel free to leave a comment below 🙂

Default image
Henner Setyono
A web developer who mainly build custom theme for WordPress since 2013. Young enough to never had to deal with using Table as layout.
Leave a Reply