本文约 6,051 字,预计阅读 16 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:编辑总问「这个样式在哪选」
主题交付后最常见的工单之一是:「我在编辑器里想用那种带左边框的引用样式,怎么选?」——你在 CSS 里写了 .entry-content blockquote { border-left: 4px solid #2563eb; },可用户想要的是同一篇文章里既有普通引用,又有蓝色引用,还有居中大字引用。纯 CSS 全局规则做不到,因为编辑器里没有任何入口让作者挑。
区块样式变体(Block Style Variations)解决这个问题:给一个区块注册多个「样式变体」,编辑器选中区块后,右侧「样式」面板出现可选项,选中后 HTML 上会加一个 is-style-{name} 的类名,你只需为这个类名写样式即可。核心区块自带的「填充/描边」按钮、图片的「圆角」等都是这么实现的。
原理分析:三种注册途径与它们的适用场合
| 途径 | API | 适合场景 | 样式来源 |
|---|---|---|---|
| PHP 注册 | register_block_style() |
主题级、服务端可控,最常用 | inline_style 或 style_handle |
| JS 注册 | wp.blocks.registerBlockStyle() |
需要动态判断、插件场景 | 编辑器与前台各加载一份 CSS |
| theme.json | styles.blocks.*.variations |
定义变体外观(WP 6.2+,Group 区块的段落样式) | 自动生成 CSS 变量与类 |
三者不是替代关系:PHP/JS 负责「让这个变体出现在选项里」,theme.json 负责「这个变体长什么样」。注册后的数据结构存放在 WP_Block_Styles_Registry 这个注册表里,取用也很直接:
$registry = WP_Block_Styles_Registry::get_instance();
$styles = $registry->get_registered_styles_for_block( 'core/button' );
类名规则是固定的:is-style-{name}。也就是说你注册的 name 为 blue-quote,最终类名就是 is-style-blue-quote。命名要用小写字母加连字符,避免与核心已有变体(outline、squared、rounded)撞车。
保姆级实操
第一步:PHP 注册,样式直接内联(最省事)
add_action( 'init', 'mimangfei_register_block_styles' );
function mimangfei_register_block_styles() {
register_block_style(
'core/quote',
array(
'name' => 'blue-quote',
'label' => __( '蓝色引用', 'mimangfei' ),
'inline_style' => '.is-style-blue-quote { border-left: 4px solid #2563eb; padding-left: 1rem; background: #eff6ff; }',
)
);
register_block_style(
'core/list',
array(
'name' => 'check-list',
'label' => __( '清单列表', 'mimangfei' ),
'inline_style' => '.is-style-check-list { list-style: none; padding-left: 0; }
.is-style-check-list li { position: relative; padding-left: 1.75rem; }
.is-style-check-list li::before { content: "✓"; position: absolute; left: 0; color: #16a34a; }',
)
);
}
inline_style 会被打印到前台和编辑器,适合几行的小样式。
第二步:样式多的时候改用 style_handle
add_action( 'init', 'mimangfei_register_block_style_with_handle' );
function mimangfei_register_block_style_with_handle() {
register_block_style(
'core/button',
array(
'name' => 'ghost',
'label' => __( '镂空按钮', 'mimangfei' ),
'style_handle' => 'mimangfei-block-styles',
)
);
}
add_action( 'enqueue_block_assets', 'mimangfei_block_style_assets' );
function mimangfei_block_style_assets() {
wp_enqueue_style(
'mimangfei-block-styles',
get_template_directory_uri() . '/assets/css/block-styles.css',
array(),
wp_get_theme()->get( 'Version' )
);
}
enqueue_block_assets 会同时作用于前台与编辑器,一处注册两端生效,比写两次 wp_enqueue_scripts + enqueue_block_editor_assets 干净。
第三步:移除核心自带的变体
add_action( 'init', 'mimangfei_unregister_block_styles' );
function mimangfei_unregister_block_styles() {
unregister_block_style( 'core/button', 'outline' );
unregister_block_style( 'core/image', 'rounded' );
}
注意调用时机:必须在核心注册之后。init 钩子默认优先级 10 通常已经晚于核心注册,若发现移除无效,把优先级调到 20 试试。
第四步:在编辑器 JS 里注册(需要动态条件时)
import domReady from '@wordpress/dom-ready';
domReady( () => {
wp.blocks.registerBlockStyle( 'core/separator', {
name: 'dashed',
label: '虚线分隔',
} );
wp.blocks.unregisterBlockStyle( 'core/quote', 'plain' );
} );
配合构建脚本打包,并在 PHP 侧注册:
add_action( 'enqueue_block_editor_assets', 'mimangfei_editor_js' );
function mimangfei_editor_js() {
wp_enqueue_script(
'mimangfei-editor',
get_template_directory_uri() . '/assets/js/editor.js',
array( 'wp-blocks', 'wp-dom-ready', 'wp-edit-post' ),
wp_get_theme()->get( 'Version' ),
true
);
}
JS 注册的变体只存在于编辑器会话中,前台样式仍要自己写 CSS——这是它不如 PHP 注册方便的地方。
第五步:用 theme.json 定义变体外观
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"styles": {
"blocks": {
"core/group": {
"variations": {
"section-muted": {
"color": {
"background": "#f3f4f6",
"text": "#1f2937"
},
"spacing": {
"padding": {
"top": "var(--wp--preset--spacing--50)",
"bottom": "var(--wp--preset--spacing--50)"
}
},
"blocks": {
"core/heading": {
"color": { "text": "#111827" }
}
}
}
}
}
}
}
}
这段会给 Group 区块生成一个名为 section-muted 的段落样式,编辑器里显示为可选变体,前台自动加 is-style-section-muted 类并输出对应 CSS。它最大的好处是外观可被用户在站点编辑器里二次修改。
第六步:给变体配上编辑器预览样式
只做前台样式,编辑在编辑器里看不到效果,体验很差。用 add_editor_style 让同一份 CSS 进编辑器:
add_action( 'after_setup_theme', 'mimangfei_setup' );
function mimangfei_setup() {
add_theme_support( 'editor-styles' );
add_editor_style( 'assets/css/block-styles.css' );
}
经典编辑器与区块编辑器都遵循这个声明;区块主题则由 theme.json 与全局样式接管,一般不需要额外加。
常见踩坑
- 注册时机太早:挂在
after_setup_theme上register_block_style可能尚未可用,标准做法是挂init。 - 变体名与核心冲突:把按钮变体命名成
outline会覆盖核心自带样式,用户已有的按钮外观突变。 style_handle指向未注册的样式:编辑器里能选中,但没有任何视觉变化,且不报错,排查时先看样式表是否真的被加载。- 只在前台加载样式:
wp_enqueue_scripts注册的 CSS 编辑器里看不到,务必用enqueue_block_assets。 unregister_block_style无效:多半是优先级太早,或目标变体是用 JS 注册的(PHP 侧无法移除)。- 案例:某内容站在主题更新后,全站文章的圆角图片突然变成直角。排查发现新版本为了统一视觉,
unregister_block_style( 'core/image', 'rounded' )移除了核心变体,而历史文章里几百张图都用了这个样式,is-style-rounded类名还在,但样式没了。正确做法是不移除,而是通过 theme.json 把rounded变体的圆角值调整成主题规范值。 - 变体过多导致选择困难:一个区块超过 5 个变体,编辑会抱怨界面复杂,建议控制在 3–4 个。
- 缓存导致新变体不显示:对象缓存或浏览器缓存未刷新时,编辑器仍读旧注册表,清缓存后再测。
总结
落地清单:小样式用 register_block_style 的 inline_style;超过十行就拆成样式文件配 style_handle;需要用户在站点编辑器里调外观的,走 theme.json 的 variations;不要轻易 unregister_block_style 核心变体,历史内容会「掉样式」。做完记得同时验证前台与编辑器两处效果,这是区块类定制最容易只做一半的地方。相关的区块复用还可以看 注册区块模式,两者配合能明显减少编辑的重复劳动;若你的主题仍是经典主题,先用 主题开发基础 补齐区块支持再考虑这一步。
