block.json
A reference to block.json parameters in WordPress
The block.json file is needed to simplify the creation and registration of blocks in WordPress.
It describes the block in JSON format and is used both on the server (php) and in the block editor (js) — that is, one file is responsible for everything.
In the official documentation there is a full list of all block.json properties.
Documentation for theme.json.
See also:
-
register_block_type_from_metadata() — block registration.
-
The parameters in block.json [official docs] (developer.wordpress.org).
- What is block.json (developer.wordpress.org)
-
Use register_block_type() to register a block.
- Use registerBlockType() to register blocks via JS.
Example block.json:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "my-plugin/notice",
"title": "Notice",
"description": "Shows warning, error or success notices...",
"icon": "star",
"category": "text",
"keywords": [ "alert", "message" ],
"textdomain": "my-plugin",
"parent": [ "core/group" ],
"render": "file:./render.php",
"script": "file:./script.js",
"style": [ "file:./style.css", "example-shared-style" ],
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"viewScript": [ "file:./view.js", "example-shared-view-script" ],
"viewStyle": [ "file:./view.css", "example-view-style" ],
"attributes": {
"message": {
"type": "string",
"source": "html",
"selector": ".message"
}
},
"supports": {
"align": true
},
"styles": [
{ "name": "default", "label": "Default", "isDefault": true },
{ "name": "other", "label": "Other" }
],
"providesContext": {
"my-plugin/message": "message"
},
"usesContext": [ "groupId" ],
"selectors": {
"root": ".wp-block-my-plugin-notice"
},
"example": {
"attributes": {
"message": "This is a notice!"
}
},
"variations": [
{
"name": "example",
"title": "Example",
"attributes": {
"message": "This is an example!"
}
}
]
}
Parameters
Core parameters:
- apiVersion — API version used by the block. Usually you should specify the latest.
- name — Unique block name with namespace (for example,
my-plugin/my-custom-block). - title — Block title displayed in the inserter.
- category — Category in which the block will be shown in the inserter. Common categories: text, media, design, widgets, theme.
- icon — Block icon in the inserter (may be a Dashicons slug or SVG).
- description — Short description of the block (more details than the title).
- keywords — Array of keywords to help find the block via search.
- textdomain — Text domain for translating the block.
Input/output and styling files for the block:
- script — JS file(s) for front-end and editor.
- style — CSS file(s) for front-end and editor.
- editorScript — JS file(s) only for the block editor.
- editorStyle — CSS file(s) only for the editor.
- viewScript — JS file(s), only for front-end.
- viewScriptModule — ES module only on the front-end.
- viewStyle — CSS file(s) only on the front-end.
Property render
In WP 6.1, the property render appeared, which specifies the path to a PHP template for dynamic rendering of the block on the front end.
- $schema(string)
- JSON schema URI to help IDE. Usually:
https://schemas.wp.org/trunk/block.json.
Default: — - apiVersion(int) (required)
- API version used by the block. It is recommended to specify the latest. For example 3.
- name(string) (required)
- Unique block name
namespace/block-name. - title(string) (required)
- Block title displayed in the inserter.
- icon(string)
- Block icon in the inserter (may be a Dashicons slug or SVG).
Default: — - category(string)
- Inserter category: text, media, design, widgets, theme, embed or custom.
Category in which the block will be shown in the inserter.
Common categories:text,media,design,widgets,theme.
Default: — - description(string)
Short description of the block (more details than the title).
Shown in the Block panel (in the right sidebar in the block editor) when the block is selected. Appears under the block title and helps the user understand the purpose in more detail.
Default: —
- keywords(array)
- Array of keywords to help find the block via search.
Default: — - textdomain(string)
- Text domain for translating the block.
Default: — - script(string|array)
- style(string|array)
- editorScript(string|array)
- editorStyle(string|array)
- viewScript(string|array)
- viewScriptModule(string|array)
- viewStyle(string|array)
Files (scripts and styles) that handle the block's functionality:
script— JS file(s) for front-end and editor.style— CSS file(s) for front-end and editor.editorScript— JS file(s) only for the block editor.editorStyle— CSS file(s) only for the editor.viewScript— JS file(s), only for front-end.viewScriptModule— ES module only on the front-end.viewStyle— CSS file(s) only on the front-end.
For all these parameters you can specify:
- Path to file (with file: prefix),
- Handle of the script/style registered via wp_register_script()/wp_register_style(),
- An array of these options.
Default: —
- render(string) (WP 6.1)
Specifies the path to a PHP template for dynamic rendering of the block on the front end.
Used if when registering the block in register_block_type() the
$render_callbackparameter is not provided.Default: —
- attributes(object)
Attributes (parameters, properties) of the block.
Keys-attributes → object with properties:
-
type(string/array of strings)
Data type (null|boolean|object|array|string|rich-text|integer|number). -
enum(array)
Fixed set of values. -
source(string)
Source (attribute|text|rich-text|html|raw|query|meta). -
selector(string)
CSS selector for extraction. -
attribute(string)
HTML attribute name when source=attribute. -
query(object)
Schema for selecting an array from markup. -
meta(string)
Post-meta key (deprecated approach). -
role(string)
content or local. default(any)
Default value.
Default: —
-
- blockHooks(object)
- Auto-insertion next to other blocks: key
namespace/block→before|after|firstChild|lastChild.
Default: — - parent(array)
Restricts usage of the block — it becomes available only inside specified parent blocks.
If you set
parent, the block disappears from the general inserter and will be available only in places where the parent block allows InnerBlocks.Values are specified as
namespace/block.You can list several parents.
Example:
{ "name": "my-plugin/child", "title": "Child block", "apiVersion": 3, "parent": [ "core/columns", "core/group" ] }In this example the block my-plugin/child can be added only inside core/columns or core/group, but not on its own.
This is convenient for “connected” blocks — for example:
- “List Item” can be inserted only inside “List”.
- “Add to Cart” — only inside “Product”.
Default: —
- ancestor(array)
List of parent blocks inside which this block may be used.
"ancestor": [ "core/group", "core/columns" ]
- Outside these parent blocks, it cannot be inserted.
- This is a kind of “inverse” variant of the
allowedBlocksparameter, which defines which child blocks can be inserted inside the current one.
Example:
{ "name": "myplugin/child-block", "title": "Child Block", "category": "widgets", "ancestor": [ "core/group" ] }Such a block can be inserted only inside core/group.
Default: —
- allowedBlocks(array) (WP 6.5)
Whitelist of blocks that can be nested inside the current block.
For example:
["core/paragraph", "core/image"]The parameter controls direct children. That is, if for the current block it is allowed to nest only, for example,
core/group, then inside core/group you can nest what is allowed for core/group.This parameter is especially useful for controlling structure — for example, a list block may allow only list items, a columns block — only columns, etc.
If you need to dynamically restrict nested blocks, use the InnerBlocks component's
allowedBlocksproperty in JavaScript, for example:<InnerBlocks allowedBlocks={ attributes.allowedBlocks } />But if the list is static, it is better to specify it directly in
block.json.Default: —
- providesContext(object)
- Exported context: key of context → the block attribute name.
Default: — - usesContext(array)
Allows a block to declare which values from the context it wants to inherit from parent blocks.
Context in Gutenberg is a mechanism to pass data downward through the block tree without explicitly passing via attributes.
How it works
- The parent block specifies in
providesContextwhich values it “gives” to children. - The child in
usesContextlists the names of these values so they can be used inside edit/save functions. - In the editor, a React component of such a block will receive these data in
props.context.
Example
{ "name": "my-plugin/child-block", "title": "Child Block", "apiVersion": 3, "usesContext": [ "postId", "postType" ] }In the JS component:
const MyChildBlock = ( props ) => { const { context } = props; return <div>Post ID: { context.postId }, Type: { context.postType }</div>; };Where it is used
- Comment blocks (
core/comment-*) get data about the current comment fromcore/comment-template. - Blocks inside the
Query LoopusequeryId,postIdand other parameters to display data for a specific post.
Features
- Works only with context that was previously declared through
providesContextby ancestors. - Values are available only within the block tree — you cannot “pull” context from a completely different place.
- If the parent does not provide the required context, the value in
props.contextwill beundefined.
Default: —
- The parent block specifies in
- version(string)
Block version (for example, 1.0.3). This is a purely informational field.
- It is not displayed anywhere in the editor UI.
- Used by WordPress internally, mainly for caching and invalidating assets (block scripts and styles).
- If a version is specified — it is added as a query string (?ver=1.0.3) when enqueuing block CSS/JS.
- If not specified — WordPress will automatically substitute the version of WordPress itself.
Default: —
- __experimental(string/boolean)
Experimental flag.
This refers to parameters that begin with the prefix
__experimental. Behavior and the key itself may change without preserving backward compatibility.Such parameters are practically not documented. If possible, better not to use.
The list of all experimental properties found in WP core 6.9 from the wp-includes/blocks folder:
supports __experimentalOnEnter: true // core/group __experimentalOnMerge: true // core/group __experimentalSettings: true // core/group __experimentalSlashInserter: true // core/navigation-link __experimentalToolbar: false // core/page-list-item __experimentalSelector: "p", // core/paragraph __unstablePasteTextInline: true, // core/paragraph __experimentalBorder: { __experimentalSkipSerialization: true radius: true color: true width: true style: true __experimentalDefaultControls: { radius: true color: true style: true width: true } } __experimentalExposeControlsToChildren: true spacing __experimentalSkipSerialization: [ "blockGap" ] __experimentalDefaultControls: { margin: false padding: false blockGap: true } blockGap __experimentalDefault: "2em" typography __experimentalFontFamily: true __experimentalFontWeight: true __experimentalFontStyle: true __experimentalTextTransform: true __experimentalTextDecoration: true __experimentalLetterSpacing: true __experimentalWritingMode: true __experimentalDefaultControls: { fontSize: true __experimentalFontFamily: true, __experimentalFontStyle: true, __experimentalFontWeight: true } __experimentalSkipSerialization: [ "fontSize", "lineHeight", "fontFamily", "fontWeight", "fontStyle", "textTransform", "textDecoration", "letterSpacing" ] color __experimentalDuotone: "img" || "> .wp-block-cover__image-background, > .wp-block-cover__video-background" __experimentalSkipSerialization: true || [ "text", "background" ] || [ "gradients" ] __experimentalSelector: "table, th" __experimentalDefaultControls: { "background": true "text": true "link": true } shadow: __experimentalSkipSerialization: true- supports(object)
- Enabling editor capabilities and styles. Connects UI and extends style/attributes.
Default: — - supports.anchor(boolean)
Includes the HTML ANCHOR control in Advanced. Usually this anchor is used as an
id=""attribute of the tag, which is preserved in content when the block is saved.
"supports": { "anchor": true, }If this parameter is enabled for a custom block whose HTML is not saved in content, you also need to specify
anchoras an attribute of the block so that it is saved in the block's JSON data:"attributes": { "anchor": { "type": "string" }, }Then in the block render file you can obtain this attribute as usual:
$attributes['anchor']
Default: false
- supports.align(boolean/array)
Alignment controls (wide|full|left|center|right). Controls block alignment in the editor.
Default: false
Possible values:
false— alignment is disabled (default).true— all alignment options allowed by the theme: wide|full|left|center|right.["left","center","right"]— explicitly listed allowable options.["wide","full"]— allow only wide and full.
Example:
{ "name": "my-plugin/banner", "title": "Banner", "supports": { "align": [ "left", "center", "right" ] } }In the editor the block will have alignment buttons, but wide and full will not be available.
aligntakes precedence overalignWide. So ifalign = ["wide","full"]andalignWide = false, the buttons will still work.- supports.alignWide(boolean)
Controls support for wide alignment for the block.
Default: true
If the theme enables wide and full alignment support [add_theme_support( 'align-wide' )], the editor will show the buttons:
To disable this capability for a specific block, set:
{ "supports": { "alignWide": false } }Then even if the theme supports it, the block cannot use
alignwide(wide width).Example: Keep only standard alignments
{ "name": "my-plugin/custom-block", "title": "Custom Block", "supports": { "align": [ "left", "right", "center" ], "alignWide": false } }aligncontrols the presence of alignment buttons:left,right,center,wide,full.alignWide— a separate flag to prohibit wide width for the block, even if the theme supports it.
- supports.ariaLabel(boolean)
Allows the
aria-labelattribute for the block, but without a separate UI field.-
If true → Gutenberg will add support for aria-label to the block. The attribute can be set manually (for example via
setAttributeor insave), but there will be no separate UI field for it. - If false (default) → the block does not support
aria-label.
Used for accessibility: you can add a textual description of the block for screen readers without loading the editor UI.
Default: false
-
- supports.className(boolean)
- Enable the wrapper class .wp-block-*.
Default: true - supports.color(object)
- Support for color properties.
Default: — - supports.color.background(boolean)
- UI for background color, adds backgroundColor and style.
Default: true - supports.color.gradients(boolean)
- UI for gradients, adds gradient and style.
Default: false - supports.color.link(boolean)
UI for link color. Enables/disables the link color picker panel.
Used for any blocks that contain text with potential
<a>inside:- paragraph
- heading
- group
- columns
- custom blocks with their own richText fields
If enabled, Gutenberg begins applying a CSS custom property to the block:
--wp--style--color--linkAnd this color affects only the
<a>inside the block, not the regular text.Default: false
- supports.color.text(boolean)
- UI for text color, adds textColor and style.
Default: true - supports.color.heading(boolean)
- UI for heading color, adds style.
Default: false - UI for button colors, adds style.
Default: false - supports.color.enableContrastChecker(boolean)
- Show contrast checker widget.
Default: true - supports.customClassName(boolean)
- Custom class field in Advanced.
Default: true - supports.dimensions(object)
- Support for dimensions.
Default: — - supports.dimensions.aspectRatio(boolean)
- UI for aspect ratio.
Default: false - supports.dimensions.minHeight(boolean)
- UI for minimum height.
Default: false - supports.filter(object)
- Support for CSS filters.
Default: — - supports.filter.duotone(boolean)
- Duotone filter.
Default: false - supports.background(object)
- Support for background properties.
Default: — - supports.background.backgroundImage(boolean)
- UI for background image.
Default: false - supports.background.backgroundSize(boolean)
- UI for background size/position/repeat.
Default: false - supports.html(boolean)
Allow editing the block HTML.
Default: true
- supports.inserter(boolean)
- Show block in the UI (inserter, transforms, Style Book).
Default: true - supports.renaming(boolean)
- Allow user to rename the block.
Default: true - supports.layout(boolean|object)
- Layout support for containers. true is equivalent to default.type: flow.
Default: false - supports.layout.default(object)
- Default values for the chosen layout type.
Default: — - supports.layout.default.type(string)
- Layout type: constrained|grid|flex.
Default: — - supports.layout.default.contentSize(string)
- Content width of children.
Default: — - supports.layout.default.wideSize(string)
- Width for alignwide children.
Default: — - supports.layout.default.justifyContent(string)
- Alignment: right|center|space-between|left|stretch.
Default: — - supports.layout.default.orientation(string)
- Orientation: horizontal|vertical.
Default: — - supports.layout.default.flexWrap(string)
- Wrap: wrap|nowrap.
Default: — - supports.layout.default.verticalAlignment(string)
- Vertical alignment: top|center|bottom|space-between|stretch.
Default: — - supports.layout.default.minimumColumnWidth(string)
- Min. column width.
Default: — - supports.layout.default.columnCount(int)
- Number of columns.
Default: — - supports.layout.allowSwitching(boolean)
Switcher for layout types.
Default: falsesupports.layout.allowEditing (boolean)
- Show layout controls in the sidebar.
Default: true - supports.layout.allowInheriting(boolean)
- Only for flow: show “Inner blocks use content width”.
Default: true - supports.layout.allowSizingOnChildren(boolean)
- Only for flex: Fit/Fill/Fixed on children.
Default: false - supports.layout.allowVerticalAlignment(boolean)
Adds vertical alignment controls. Only for
flex."layout": { "default": { "type": "flex" }, "allowVerticalAlignment": true },Default: true
- supports.layout.allowJustification(boolean)
- flex and constrained: Justify controls.
Default: true - supports.layout.allowOrientation(boolean)
- Only for flex: orientation control.
Default: true - supports.layout.allowCustomContentAndWideSize(boolean)
- Only for constrained: custom content/wide size.
Default: true - supports.multiple(boolean)
- Allow multiple instances of a block in a post.
Default: true - supports.reusable(boolean)
- Allow conversion to reusable block.
Default: true - supports.lock(boolean)
- Allow user to change the lock state.
Default: true - supports.position(object)
- Positioning support.
Default: — - supports.position.sticky(boolean)
- Sticky position relative to the parent.
Default: false - supports.spacing(object)
- Spacing support.
Default: — - supports.spacing.margin(boolean/array)
- UI for margin. Array: sides top|right|left|bottom or axes vertical|horizontal.
Default: — - supports.spacing.padding(boolean/array)
- UI for padding. Array: sides or axes.
Default: — - supports.shadow(boolean/object)
- Shadow support (box-shadow).
Default: false - supports.typography(object)
- Typography support.
Default: — - supports.typography.fontSize(boolean)
- UI for font-size, adds fontSize and style.
Default: false - supports.typography.lineHeight(boolean)
- UI for line-height, stored in style.
Default: false - supports.typography.textAlign(boolean/array)
- Text alignment toolbar (left|center|right).
Default: false - supports.interactivity(boolean/object)
- Using Interactivity API.
Default: false (if boolean) - Compatibility with client navigation IA.
Default: false - supports.interactivity.interactive(boolean)
- Are there IA directives.
Default: false - supports.splitting(boolean)
- Enable split on Enter/paste.
Default: false - supports.__experimentalOnEnter
Handling Enter inside the block (exit/split container, not exact).
Where it occurs:
core/group,core/columnsMeaning (not exact): enables special handling of Enter — the editor decides what to do when Enter is pressed in the last
RichTextinside the block (for example, exit the container and create a newcore/paragraphafter the block).Example:
- In a container block (conditional my-plugin/container) you can set:
"supports": { "__experimentalOnEnter": true }, so pressing Enter in the end of the last paragraph moves the cursor outside the container and creates a newcore/paragraph.
Default: false
- In a container block (conditional my-plugin/container) you can set:
- supports.__experimentalOnMerge
Logic for merging the block with neighbors on Backspace/Delete (not exact).
Where it occurs:
core/groupMeaning (not exact): enables custom behavior when blocks are merged — typically when the cursor is at the start of the block and the user presses Backspace/Delete, the editor tries to merge the block with the previous one. For containers this flag allows them to intercept the event and, for example, move the neighboring block inside/outside the container instead of the standard delete/merge.
Example:
- For a custom wrapper block you can enable:
"supports": { "__experimentalOnMerge": true }, so that Backspace at the start of the block does not delete the previous paragraph but moves it inside the container.
Default: false
- For a custom wrapper block you can enable:
- supports.__experimentalSettings
Internal Gutenberg flag to enable additional block settings/panels (not exact).
Where it occurs: in some core blocks, for example
core/group.Meaning (not exact): A service property that marks a block as using additional editor capabilities (settings panels, options, UI). The exact set of effects is not documented and can vary between Gutenberg versions. It is recommended not to use in custom blocks unless necessary, as the API is unstable and geared toward core needs (not exact).
Example:
- In some core blocks you can see:
"supports": { "__experimentalSettings": true }, which enables extended panels in the inspector (the exact panels vary by version, not exact).
Default: false
- In some core blocks you can see:
- supports.__experimentalSlashInserter
Enables slash insertion (/), showing a list of blocks/commands directly in block text.
Where it occurs: text blocks (
core/heading, etc.).Goal: Makes the block participate in the slash inserter mechanic: when typing "/" in a RichText field of the block, a pop-up list of blocks and commands appears (as in a paragraph).
Useful for text blocks that should feel like a standard paragraph/heading.
Historically also used to enable auto-completion of links via
[[…]], but now this behavior is mostly global.Example:
- For a text block my-plugin/lead-paragraph:
"supports": { "__experimentalSlashInserter": true } — allows a user to type /image and insert core/image directly from the hint without leaving the block.
Default: false
- For a text block my-plugin/lead-paragraph:
- supports.__experimentalToolbar
Controls the display of the standard block toolbar (can be hidden for internal blocks).
Meaning (not exact): controls the visibility of the standard block toolbar (the icons panel above the block) for particular “internal”/utility blocks.
For blocks such as
core/page-list-itemthis means “do not show the block’s own toolbar, control the block via the parent (for example,core/page-list)”.Recommendations:
- Use only if you are creating a technical internal block that should not have its own editing interface (toolbar) directly.
Example:
- An internal block element that is used only inside the parent block (for example, a menu item in a custom navigation block) can be declared as:
"supports": { "__experimentalToolbar": false }, so control goes only through the parent’s toolbar.
Default: true (by meaning; core explicitly sets false for some internal blocks)
- supports.__experimentalSelector
Overrides the CSS selector to which global styles (theme.json) apply to the block.
Example:
- ".my-custom-classname"
- "p"
- ".wp-block-button .wp-block-button__link"
Purpose: Allows specifying an alternative CSS selector to which global styles (theme.json / Global Styles) will apply for this block.
Default: WordPress uses a selector like
.wp-block-<block-name>. If the block does not use such wrapper or you need to style an inner element (for example, the<form>or<a>in a button), you can use this property.Typical uses:
- Block does not render the standard class
.wp-block-…, but you want global styles to apply. - Need global styles to apply not to the wrapper-div, but to the “real” element, for example:
- Form block: "__experimentalSelector": "form"
- Button-link: "__experimentalSelector": ".wp-block-button .wp-block-button__link"
Features:
-
For global styles to work correctly the block must be registered via block.json through register_block_type_from_metadata(), otherwise selector information is not available to the PHP part.
- The flag is still marked as experimental, but considered relatively mature and actively used in core blocks.
Risks:
-
Incorrectly chosen selector may affect not only the block itself but also nested elements (especially for containers like
<form>).Example:
-
For a form block that renders only
<form class="my-form">…</form>without wrapper.wp-block-*, you can specify:
"supports": { "__experimentalSelector": "form.my-form" }, so global color/typography styles from theme.json apply to the<form>tag.Default: uses the standard selector
.wp-block-<block-name>
- supports.__unstablePasteTextInline
Special handling of pasting text as inline content without splitting into blocks (not exact).
Where it occurs:
core/paragraph,core/headingand other text blocks with RichText.Meaning (not exact):
-
Enables a special paste handling mode in RichText fields of the block:
-
paste is treated as “inline text” without breaking or creating new blocks,
- complex pastes (multiline text, HTML) are simplified to text and pasted at the current cursor position.
-
- Used by core to make such blocks behave more predictably when pasting text from clipboard (headings, paragraphs, etc.).
Status: This property is marked as
__unstable, i.e., even less stable than __experimental.In custom blocks better to enable it only if you precisely reproduce core text block behavior and are prepared for possible API changes.
Example:
- For a custom text block based on RichText:
"supports": { "__unstablePasteTextInline": true }— pasting from clipboard (for example Word/Google Docs) will be converted to plain text and inserted into the current block, without creating new blocks.
Default: false
-
- supports.__experimentalExposeControlsToChildren
Shares the container block's settings panel with its child blocks.
The flag is used for container blocks with InnerBlocks (for example, button groups) so that part of the parent's settings (layout, alignment, margins, etc.) remains accessible even when an inner block is selected.
When this property is enabled the inspector can continue to show/apply some parent block controls when a child block is clicked, easing work with composite blocks.
The exact behavior and the set of “shared” controls depend on the editor version and may change.
Example:
{ "name": "my-plugin/buttons-group", "supports": { "__experimentalExposeControlsToChildren": true, "spacing": { "blockGap": true, "margin": [ "top", "bottom" ] } } }Default: false
- supports.__experimentalBorder
Enables border support for the block (color, width, style, radius) and configures visible controls.
Enabling this shows corresponding panels in the block inspector, and the chosen values go into style attributes (
style.border.*) and/or CSS classes. Used by many core blocks.Key object keys:
radius— enables the corner radius control.color— enables border color selection.width— enables border width control.-
style— enables line style (solid, dashed, dotted, etc.). -
__experimentalDefaultControls— object with the same keys (radius,color,width,style) that controls which controls are active by default in the UI (for example, you can enable only radius). __experimentalSkipSerialization— if true, border styles will not be automatically serialized to the block wrapper element. Values will still be stored in style attributes and can be applied manually viauseBorderPropsin JS orget_block_wrapper_attributes()in PHP to any element.
Additionally:
- If any of the keys (radius, color, width, style) is not specified, the corresponding control is hidden.
- If the theme does not include support for borders/appearance tools (for example, via theme.json or
add_theme_support( 'border' )), the UI may be hidden even when the block has this support enabled. - In newer WordPress versions this support is planned to be moved to a stable key border (without the prefix), while the old
__experimentalBorderwill continue to be supported for some time as an alias.
Example:
{ "name": "my-plugin/box", "supports": { "__experimentalBorder": { "__experimentalSkipSerialization": true, "radius": true, "color": true, "width": true, "style": true, "__experimentalDefaultControls": { "radius": true, "color": true, "style": true, "width": true } } } }Default: false - Border panel is disabled and all nested properties are off as well.
- selectors(object)
Allows the block to configure CSS selectors on the element that styles are generated for.
You can override CSS selectors at three levels:
- Root
- Feature level
- Subfeature level
Root selector
The root selector is the block’s main CSS selector.
All blocks must have a main selector under which their style declarations will be collected. If not set, the default is
.wp-block-<name>:{ ... "selectors": { "root": ".my-custom-block-selector" } }Feature selectors
Feature selectors relate to styles for block supports, e.g., border, color, typography, etc.
The block may want to apply styles of individual features to different elements inside it. For example, colors to the wrapper, typography to the inner heading only.
Example
{
...
"selectors": {
"root": ".my-custom-block-selector",
"color": ".my-custom-block-selector",
"typography": ".my-custom-block-selector > h2"
}
}
Subfeature selectors
These selectors relate to individual styles provided by a particular block feature, e.g., background-color.
For a subfeature you can generate styles under its own unique selector. This is especially useful when one of the subfeatures cannot be applied to the same element as other subfeatures of the same feature.
For example — text-decoration. Browsers render this property differently, making it hard to override if added to the wrapper element. Assigning a separate selector to text-decoration allows targeting exactly those elements to which it should apply.
{
...
"selectors": {
"root": ".my-custom-block-selector",
"color": ".my-custom-block-selector",
"typography": {
"root": ".my-custom-block-selector > h2",
"text-decoration": ".my-custom-block-selector > h2 span"
}
}
}
Shorthand
Instead of specifying a selector for each subfeature, you can provide a single selector as a string for the corresponding feature. This is how it is done for color in the examples above.
Fallbacks
If a selector for a particular feature is not configured, it falls back to the block root selector. Similarly, if a subfeature does not have a custom selector, the feature parent’s selector is used, and if that is absent — the block root selector.
Rather than repeating the same selector for multiple subfeatures you can specify a common selector as the root for the parent feature, and define unique selectors only for the differing subfeatures.
Example:
{
...
"selectors": {
"root": ".my-custom-block-selector",
"color": {
"text": ".my-custom-block-selector p"
},
"typography": {
"root": ".my-custom-block-selector > h2",
"text-decoration": ".my-custom-block-selector > h2 span"
}
}
}
In the example above color.background-color is not explicitly set. Since color also does not define a root, color.background-color will be generated under the block’s root selector — .my-custom-block-selector.
For subfeatures like typography.font-size a fallback to the parent feature’s selector will be used, since it is defined — .my-custom-block-selector > h2.
Default: —
- selectors.root(string)
- Primary CSS class of the block, replaces .wp-block-*.
Default: — - selectors.border(string/object)
- Sselectors for borders: root|color|radius|style|width.
Default: — - selectors.color(string/object)
- Sselectors for color: root|text|background.
Default: — - selectors.dimensions(string/object)
- Sselectors for dimensions: root|aspectRatio|minHeight.
Default: — - selectors.spacing(string/object)
- Sselectors for spacing: root|blockGap|padding|margin.
Default: — - selectors.typography(string/object)
- Sselectors for typography: root|fontFamily|fontSize|fontStyle|fontWeight|lineHeight|letterSpacing|textDecoration|textTransform.
Default: — - styles(array)
Allows defining alternative styles for the block.
When a user selects a particular style, a CSS class is-style-{name} is added to the block wrapper, which can be styled in CSS.
Each object inside the array describes a separate style and can contain:
-
name(string, required)
Unique machine name of the style (used in the CSS class). -
label(string, required)
Readable style name displayed in the UI. Can be localized. - isDefault(boolean)
If true, the style will be selected by default.
Default: false
Also these style variations can be configured in the style editor in the admin:
Example:
{ "styles": [ { "name": "default", "label": "Default", "isDefault": true }, { "name": "outline", "label": "Outline" }, { "name": "fancy", "label": "Fancy Style" } ] }As a result, selecting the
outlinestyle gives the block the class:<div class="wp-block-my-block is-style-outline"></div>
Usage:
- The theme or plugin should define CSS for the corresponding classes.
- Useful for quick style switching (for example, filled vs outlined buttons).
You can register styles for core blocks as well by adding your own variants:
Via PHP:
register_block_style( 'core/image', [ 'name' => 'outline', 'label' => 'Outline', 'inline_style' => <<<'CSS' .wp-block-image.is-style-shadowed img { box-shadow: 0 8px 24px rgba(0,0,0,.2); } CSS, ] );Via JS:
// In your editor.js loaded only in the editor. wp.domReady( () => { wp.blocks.registerBlockStyle( 'core/paragraph', { name: 'outline', label: 'Outline' } ); // Remove built-in style: // wp.blocks.unregisterBlockStyle( 'core/image', 'rounded' ); } );Default: — (empty array)
-
- example(object)
- Preview data for Inspector Help.
Default: — - example.viewportWidth(int)
- Width of the preview iframe.
Default: 1200 - example.attributes(object)
- Attributes for the preview.
Default: — - example.innerBlocks(array)
- Child blocks for the preview.
Default: — - variations(string/array)
- Block variations. Path to PHP returning an array, or an array of objects.
Default: — - variations[].name(string) (required)
- Machine-readable variation name.
Default: — - variations[].title(string) (required)
- Variation title.
Default: — - variations[].description(string)
- Variation description.
Default: — - variations[].category(string)
- Variation category.
Default: — - variations[].icon(string)
- Variation icon.
Default: — - variations[].isDefault(boolean)
- Set variation as default.
Default: false - variations[].attributes(object)
- Override attributes.
Default: — - variations[].innerBlocks(array)
- Initial configuration of nested blocks.
Default: — - variations[].example(object)
- Preview data for variation.
Default: — - variations[].scope(array)
- Where the variation is available: inserter|block|transform.
Default: ["inserter","block"] - variations[].keywords(array)
- Keywords for searching variation.
Default: — - variations[].isActive(array)
- List of attributes to compare variation activity.
Default: —





