How to Add Custom Block Styles (theme.json vs CSS)

January 16, 2026
How to Add Custom Block Styles (theme.json vs CSS)

How to Add Custom Block Styles (theme.json vs CSS)

Custom block styles are one of the cleanest ways to give editors “approved design options”
without letting them freestyle layouts.
In modern WordPress, you can add styles in two main ways:

  • theme.json (Global Styles / block style variations)
  • Classic CSS (theme stylesheet + optional register_block_style())

This article explains when each approach wins, how to implement both safely,
and how to keep output predictable across themes and environments.

What “Custom Block Styles” Means

A “block style” is a named variation that appears in the editor under:

Block sidebar → Styles

When selected, WordPress adds a class to the block:

is-style-your-style-name

Your theme then provides CSS for that class.

Choose the Right Approach

Use theme.json When

  • You are building a block theme or heavily using Global Styles
  • You want design tokens (colors, typography, spacing) centrally managed
  • You want consistent editor + front-end styling alignment
  • You want to leverage core style presets instead of custom CSS everywhere

Use CSS When

  • You are using a classic theme
  • You want full control with minimal Gutenberg coupling
  • You only need a few simple variations
  • You want styles to work even if theme.json evolves later

In practice, many pro builds are hybrid:

  • theme.json for global design tokens and editor constraints
  • CSS for specific component-like styles

Option A: Add Block Styles via PHP + CSS (Classic Theme Friendly)

This is the most flexible approach and works in both classic and block themes.
You register a style name and provide CSS for the generated class.

Register a Custom Style for the Button Block

<?php
add_action( 'init', function () {
  register_block_style(
    'core/button',
    array(
      'name'  => 'soft-pill',
      'label' => __( 'Soft Pill', 'your-textdomain' ),
    )
  );
} );

This exposes a new “Soft Pill” style in the editor.
Now add CSS in your theme stylesheet:

/* Button: Soft Pill */
.wp-block-button.is-style-soft-pill .wp-block-button__link {
  border-radius: 9999px;
  padding: 0.75em 1.25em;
  text-decoration: none;
}

Because the class is deterministic, this is easy to maintain and easy to review in Git.

Example: Style Variation for Quote Block

<?php
add_action( 'init', function () {
  register_block_style(
    'core/quote',
    array(
      'name'  => 'callout',
      'label' => __( 'Callout', 'your-textdomain' ),
    )
  );
} );
/* Quote: Callout */
.wp-block-quote.is-style-callout {
  border-left-width: 0.4em;
  padding-left: 1em;
}

Option B: Define Custom Block Styles in theme.json (Block-Theme Native)

In block themes, you can add styles directly in theme.json
under the block’s styles or variations-like structure.

A practical approach is to:

  • Define the style variation name and label in theme.json
  • Still provide custom CSS for the is-style-* class if needed

Example (illustrative structure):

{
  "version": 2,
  "styles": {},
  "settings": {},
  "customTemplates": [],
  "templateParts": [],
  "blocks": {
    "core/button": {
      "styles": [
        {
          "name": "soft-pill",
          "label": "Soft Pill"
        }
      ]
    }
  }
}

Then use CSS the same way:

.wp-block-button.is-style-soft-pill .wp-block-button__link {
  border-radius: 9999px;
}

The advantage is that the style becomes part of the theme’s design system.
The downside is that theme.json is more tightly coupled to Gutenberg and theme architecture.

Which Is More Maintainable?

CSS + register_block_style() Wins for Most Classic Themes

  • Works everywhere
  • Easy to diff and review
  • Doesn’t require a block-theme structure
  • Does not depend on theme.json syntax changes

theme.json Wins When You Want a Centralized Design System

  • Design tokens are consistent
  • You can limit editor features (colors/typography/spacing)
  • Editor and front end stay aligned more naturally

Best Practice: Keep Style Names Stable

Once published, keep your style name stable:

  • soft-pill should not become pill-soft

Why? The class is stored in post content.
Renaming a style breaks existing posts unless you migrate content.

Best Practice: Avoid Too Many Styles

A style panel with 10 variations becomes a design system you must support forever.
Keep your list short and intentional:

  • 1–3 styles per block is usually enough
  • Prefer “semantic” styles (Callout, Warning, Note) over aesthetic styles (Blue, Rounded)

Best Practice: Match Editor and Front-End Styles

If the editor preview doesn’t match the front-end, editors will make bad decisions.
Ensure block styles load in both places:

  • Front-end: normal enqueue
  • Editor: enqueue_block_editor_assets or editor stylesheet support

Load Editor CSS for Block Styles

<?php
add_action( 'enqueue_block_editor_assets', function () {
  wp_enqueue_style(
    'wpct-editor-block-styles',
    get_theme_file_uri( '/assets/css/editor-block-styles.css' ),
    array(),
    '1.0.0'
  );
} );

If you already have a unified stylesheet, you can also reuse it carefully.

Example: Add a “Note” Style for Paragraph

This is a clean, semantic style that can be used across content.

<?php
add_action( 'init', function () {
  register_block_style(
    'core/paragraph',
    array(
      'name'  => 'note',
      'label' => __( 'Note', 'your-textdomain' ),
    )
  );
} );
p.is-style-note {
  padding: 1em;
  border-left-width: 0.35em;
}

Common Mistakes

  • Creating style names based on colors (hard to maintain)
  • Renaming style slugs after publishing
  • Not loading CSS in the editor
  • Using block styles as a substitute for a real component system

Summary

  • Block styles add “approved variations” without giving editors full design freedom
  • register_block_style() + CSS is the most portable approach (especially for classic themes)
  • theme.json is best when you want a centralized design system for a block theme
  • Keep style slugs stable and the style list short
  • Load the same styles in both editor and front-end for reliable previews

If you’re building WP Code Tips content, a practical angle is:
use PHP + CSS for most client themes, and highlight theme.json as the design-system layer
when moving into block themes.

Avatar

Written by

satoshi

I’ve been building and customizing WordPress themes for over 10 years. In my free time, you’ll probably find me enjoying a good football match.