Block Style Variations (block styles) enable developers to give content creators pre-made styling options for core blocks, ensuring brand consistency and streamlining content production. Using block styles can also eliminate the need to create custom blocks, reducing code maintenance.
In this guide, you’ll learn several ways to add custom block
styles in WordPress, whether you’re working with a theme or a
plugin. We’ll cover options using JSON (theme.json
),
PHP (register_block_style()
), and JavaScript, with
clear guidance on which method suits which situation.
You will also learn how to remove core block styles from the editor and curate the experience for your content creators.
The
theme.json
code refers to block styles as “variations” (short for “block
style variations”), which is sometimes confused with block variations or Global Styles variations. This post refers to
these as “block styles” to avoid confusion.
This post starts with simple examples and gradually introduces more advanced methods for adding block styles, from quick theme tweaks to plugin-based approaches.
The code referenced in this post is also available on GitHub:
- Theme: plain-pauli
- Plugin: block-styles
You’ll want to have a basic understanding of CSS to follow
along. Being comfortable with theme.json
is also key,
and knowing a bit about PHP and WordPress hooks will definitely
come in handy.
To follow along or use the example code, you can use Studio, our free and open source local development environment, available for Mac and Windows.
- What are custom block styles?
- Method 1: add a block style via a JSON file (/styles folder)
- Method 2: register block style in PHP and style it via theme.json
- Method 4: register block styles using JavaScript + CSS
- Optional: removing unwanted core block styles
- Summary: custom block styles at a glance
- Resources to learn more
What are custom block styles?
Custom block styles let you define alternative visual treatments for existing blocks, like adding a border, changing the background, or tweaking typography.
When the block is selected, these custom styles will appear in the Styles panel within the editor sidebar, giving content creators easy ways to apply consistent, reusable design patterns. You can create as many custom block styles as you’d like.
Below you’ll find an example of the Image block. The Styles panel below shows four styles: Default, Rounded, Purple Border, and Red Border (which is the selected style showing in the editor).

We’ll walk through six ways to add custom block styles in WordPress, from simple theme edits to more advanced methods.
Method 1: add a block style via a JSON
file (/styles
folder)
- Best for: Theme developers
- Where you would typically use it: Commonly in themes
- Version requirements: WordPress 6.6 or higher
with
theme.json
v3
For theme developers, the most streamlined way to add custom block styles to a theme is to add a new file to the /styles folder.
This method requires upgrading the theme.json
schema to v3, which is
only available in WordPress 6.6 and above. As a theme developer,
you would either require your users to install the Gutenberg plugin
or update the minimum requirement for your theme to WordPress 6.6
to ensure everything works as intended.
Say we wanted to add a blue border style called
image-blue-border.json
.
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"title": "Blue Border",
"slug": "blue-border",
"blockTypes": [ "core/image" ],
"styles": {
"border": {
"color": "#00f9ff",
"style": "solid",
"width": "4px",
"radius": "15px"
},
"shadow": "var(--wp--preset--shadow--natural)"
}
}
With theme.json
v3, the metadata information for a
block’s style is automatically registered within the WP_Block_Styles_Registry:
- The
title
is the same as thelabel
from theregister_block_style code
. - The
slug
is similar to thename
property of theregister_block_style function
. - The
blockTypes
property can be used to assign a style to a particular block or series of blocks.

The code "shadow":
"var(--wp--preset--shadow--natural)"
refers to the preset
“Natural” shadow style in WordPress. By using a preset
variable, your block will automatically reflect any global style
changes, keeping your design consistent across themes and
updates.
Once you save your code changes:
- Your new style is added to the Styles panel for that particular block.
- The block editor shows a preview when you hover over the button.
- The Styles engine attaches the CSS class
is-blue-border
to the block in the editor and on the frontend. - When opening the Global Styles via Styles → Blocks → Image, the styles can be changed by the user for the whole site.
To organize your block style code, you can create a subfolder in
the styles folder called /blocks
and keep them all
together. A few theme developers found they could reduce the length
of their functions.php
file considerably by
implementing subfolders instead.
Method 2: register block style in PHP
and style it via theme.json
- Best for: Theme developers
- Where you would typically use it: In the theme.json file and in functions.php
- Version requirements: WordPress 6.6 or higher
with
theme.json
v3
To add a custom block style using this method, you’ll need to
register the style and add your stylings in the
theme.json
file.
Register block style
In your functions.php
file, use the register_block_style()
function to
set the two mandatory arguments (additional optional arguments are
covered below):
name
: The identifier of the style used to compute a CSS class.label
: A human-readable label for the style.
Once set, you can add them to the init
hook in your
theme.
function my_style_red(){
register_block_style(
'core/image',
array(
'name' => 'red-border',
'label' => __( 'Red Border', 'my-theme' )
)
);
}
add_action( 'init', 'my_style_red' );
Add styling to
theme.json
We’ll add some styling for the red-border
variation
to the theme.json
file. It’s placed within the
styles.blocks.core/image
section, as we’re making
changes to the Image block.
"styles": {
"blocks": {
"core/image":{
"variations": {
"red-border":{
"border": {
"color":"#cf2e2e",
"style": "solid",
"width": "4px",
"radius":"15px"
}
}
}
},
These two code snippets work together because the
name
used in the register_block_style()
function in your functions.php
file and the
variations’ name
arguments in your
theme.json
file are identical.
This method produces the same editor and frontend results as
using a JSON file in the /styles
folder:
- The style will be visible in the editor and on the frontend.
- It is also available via the Editor → Styles → Blocks → Image section for global customization.

If the styles available in theme.json
aren’t
enough, you have a few options:
- You can use the
CSS
property in JSON notation. The WordPress.org per-block CSS withtheme.json
article provides a good summary of how to do this. - You can use any of the methods below and add them to your
functions.php
file. - You can register the block style via
register_block_style()
and include the CSS in your theme’s overallstyle.css
file, referencing the block and style class name. That being said, this is not recommended as these styles will always load, even if the block isn’t in use. A bug is also preventing the styles from loading on the frontend. - You can use block stylesheets to only load the styles when the block is used, as outlined in the WordPress Theme handbook tutorial on block stylesheets.
Method 3: add a block style with
register_block_style()
(PHP)
The register_block_style()
function has three
additional and optional parameters. They are listed on the
documentation page for the WP_Block_Styles_Registry class that handles the
registration and management of block styles.
style_data
: Atheme.json
-like object used to generate CSS.inline_style
: Inline CSS code that registers the CSS class required for the style.style_handle
: The handle of a previously registered style to enqueue alongside the block style.
See the documentation for
register_block_style()
for more information.
3a. Use the style_data
parameter
- Best for: Plugin developers and theme developers
- Where you would typically use it: In plugin
files or
functions.php
- Version requirements: WordPress 6.6 or higher
Although block styles have been a fundamental way that WordPress
works since 5.0, the style_data
parameter was added in
WordPress 6.6.
This method for defining block styles uses “a
theme.json
-like object,” meaning an array of nested
styles in a format that very closely resembles the styles section of the theme.json
file. At the root level, the styles are applied to the block(s)
that you define with the block_name
array.
If you are familiar with theme.json
structure, you
can use this method to add additional styles. This method enables
those styles in Editor → Styles → Blocks and users can
make changes there.
As you can see, the array notation for this parameter follows JSON closely.
The theme.json
reads:
"border": {
"color":"#cf2e2e",
"style": "solid",
"width": "4px",
"radius":"15px"
}
The array in PHP reads:
array(
'border' => array(
'color' => '#f5bc42',
'style' => 'solid',
'width' => '4px',
'radius' => '15px'
),
To further demonstrate this idea, this function adds an orange border with a box shadow using the “sharp” shadow style preset.
function my_orange_border() {
register_block_style(
array( 'core/image' ),
array(
'name' => 'orange-border',
'label' => __( 'Orange Border', 'pauli' ),
'style_data'=> array(
'border' => array(
'color' => '#f5bc42',
'style' => 'solid',
'width' => '4px',
'radius' => '15px'
),
'shadow' => array(
'var(--wp--preset--shadow--sharp)'
)
)
)
);
};
add_action( 'init', 'my_orange_border' );

Of the three parameters, only the style_data
information will be added to the global style section in the site
editor and can be edited by the site owner. The other two add the
styles to the Styles panel, and there is no edit path within the
UI.
3b. Use the inline_style
parameter
- Best for: Plugin developers and theme developers
- Where you would typically use it: In the main
plugin PHP file or
functions.php
- Version requirements: WordPress 5 or higher
The value for the inline_style
parameter is a
combination of the CSS selector and the CSS properties.
function my_double_frame_styles() {
register_block_style(
'core/image',
array(
'name' => 'double-frame',
'label' => __( 'Double-Frame', 'pauli' ),
'inline_style' => '.wp-block-image.is-style-double-frame
img { border: 10px ridge lightgreen; }'
)
);
}
add_action( 'init', 'my_double_frame_styles' );

The class name follows standard block editor naming conventions.
Each core block’s class name contains the prefix
wp-block
+ the block name, like image
. It
is then followed by the block style prefix is-style
and the registered style slug
, like
double-frame
.
The class name
.wp-block-image.is-style-double-frame
is followed by
the style that you want to attach to the block. Here you see the
CSS values for the border property for the image element
(img
). It adds a ridged, light green 1px
border.
You can have quite a few CSS properties combined in the
inline_style
parameter for the function, but it may
become hard to read and manage.
3c. Use the style_handle
parameter
- Best for: Plugin developers and theme developers
- Where you would typically use it: In plugin
files or
functions.php
- Version requirements: WordPress 5 or higher
For more elaborate styles, consider placing the CSS in a
separate file and using wp_enqueue_style()
to load it
on the frontend and backend. Then use the style_handle
parameter in the register_block_style()
function.
Here is some example code using this method to add a purple border style.
function my_purple_border_styles() {
wp_enqueue_style(
'my-image-block-style',
plugin_dir_url(__FILE__) . '/my-purple-border.css',
array( 'wp-edit-blocks' ),
'1.0'
);
register_block_style(
'core/image',
array(
'name' => 'purple-border',
'label' => __( 'Purple Border, slightly rounded', 'pauli' ),
'style_handle' => 'my-image-block-style'
)
);
}
And here is the accompanying my-purple-border.css
file, which is placed into the plugin’s root folder.
.is-style-purple-border img {
border: 6px solid purple;
border-radius: 15px;
box-shadow: 10px 5px 5px #e090fc;
};
The image block now has a purple border with a pinkish shadow style.

Note: There is also a bug report open about the stylesheet loading even when the block styles aren’t used. Because of this, it’s not recommended for complex CSS.
Method 4: register block styles using JavaScript + CSS
- Best for: Plugin developers and theme developers
- Where you would typically use it: In a
separate
*.js
file, enqueued in a plugin file, or infunctions.php
- Version requirements: WordPress 5 or higher
Compared to using the separate JSON file to add a block style variation, using JavaScript is more elaborate. It has three parts:
- PHP: To enqueue the necessary files
- JavaScript: To register the block style
- CSS: To style the block
The wp_enqueue_script()
function adds JavaScript
files to a webpage. It’s not JavaScript itself, but rather a
WordPress PHP function that’s often used in WordPress theme or
plugin development. For this example, we can store the
.js
file in the theme’s /js/
subdirectory
and name it curate-core.js
.
The example code loads our custom curate-core.js
file after the necessary WordPress block editor scripts. It’s added
to the bottom of the page for better performance and is hooked into
enqueue_block_editor_assets
so it only loads in the
editor.
This code example goes into the theme’s
functions.php
file or your plugin’s *.php
file.
function pauli_block_editor_scripts() {
wp_enqueue_script(
'pauli-editor',
get_theme_file_uri( '/js/curate-core.js' ),
array( 'wp-blocks', 'wp-dom' ),
wp_get_theme()->get( 'Version' ), true
);
}
add_action( 'enqueue_block_editor_assets', 'pauli_block_editor_scripts' );
This code should go in the JavaScript file
curate-core.js
:
wp.domReady( function() {
wp.blocks.registerBlockStyle(
'core/image', {
name: 'black-border',
label: 'Black Border',
}
);
} );
You can then add our block styles to your theme’s
style.css
file using the automatically added class
name, is-style-black-border
.
.is-style-black-border img {
border: 15px ridge black;
}
Due to a bug, you need to add the
style.css
to the frontend. It doesn’t seem to be
automatically loaded. You use wp_enqueue_style()
and
then use the hook wp_enqueue_scripts
.
Then you’d add the following to your functions.php
or plugin file:
function enqueue_theme_styles() {
wp_enqueue_style(
'my-theme-styles',
get_stylesheet_uri(), // This gets your style.css
array(),
wp_get_theme()->get( 'Version' )
);
}
add_action( 'wp_enqueue_scripts', 'enqueue_theme_styles' );
You also need to add style.css
to the block editor
so your users can see how the block style looks when they are
working on the post or page.
//add style.css to editor
function add_theme_editor_styles() {
add_editor_style( 'style.css' );
}
add_action( 'after_setup_theme', 'add_theme_editor_styles' );

Optional: removing unwanted core block styles
Now that you know how to add block styles to your theme or your plugin, you might also want to remove some additional block styles that come with the block editor out of the box.
There are two functions you’ll need to address:
- The PHP function
unregister_block_style()
- The JavaScript function
unregisterBlockStyle()
Block styles can only be unregistered in the same coding language used to register them. All core blocks are registered with JavaScript.
The example code below removes the additional block style for
the image block called rounded
.
wp.domReady( function() {
wp.blocks.unregisterBlockStyle( 'core/image', [ 'rounded' ] );
} );
For more ways to modify the block editor, read 15 ways to curate the WordPress editing experience.
Summary: custom block styles at a glance
You now know the six ways to register block styles for the WordPress block editor. Here’s a quick recap of what we covered:
Block Style Added in Example Code | Language | Theme/Plugin | Parameter | File | Global Styles |
---|---|---|---|---|---|
![]() |
PHP+ | Theme | theme.json |
yes | |
![]() |
JSON | Theme | image-blue-border.json |
yes | |
![]() |
PHP | Theme/Plugin | style_data |
yes | |
![]() |
PHP | Theme/Plugin | style_handle |
.css | no |
![]() |
PHP | Theme/Plugin | inline_style |
no | |
![]() |
JS | Theme/Plugin | .js + .css + .php |
no |
The easiest method is to add a JSON file to the
/styles
folder using the theme.json
format. Another option uses minimal PHP in your
functions.php
file alongside your
theme.json
configuration. Both approaches add block
styles to the Styles panel in the editor, where users can apply and
customize them.
Plugin developers can use the style_data
parameter
to achieve similar results, including integration with Global
Styles.
Other plugin-based methods—using inline_style
,
style_handle
, or JavaScript—don’t support Global
Styles editing, but still make the styles selectable in the
editor.
Keep in mind that the first three methods (JSON file,
theme.json
with PHP, and style_data) require WordPress
6.6 or higher. To support older WordPress versions, you’ll need to
use one of the other available approaches.
Resources to learn more
Want to learn even more about block styles and block variations? Here are some resources to check out:
YouTube
Make.WordPress Dev Note
WordPress Developer Blog
- Styling sections, nested elements, and more with Block Style Variations in WordPress 6.6
- Leveraging theme.json and per-block styles for more performant themes
- Per-block CSS with theme.json
- Beyond block styles, part 1: using the WordPress scripts package with themes
- Beyond block styles, part 2: building a custom style for the Separator block
- Beyond block styles, part 3: building custom design tools
Block Editor Handbook
Themes Handbook
Read more https://wordpress.com/blog/2025/05/07/custom-block-styles/