本文约 7,718 字,预计阅读 20 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:样式配置的入口变了
过去做主题,全局样式的套路是:在 style.css 里定义一堆 CSS 变量,再用 add_theme_support() 逐项声明——editor-color-palette、editor-font-sizes、custom-line-height、responsive-embeds……声明项越来越多,而且 PHP 里写的调色板还得在 CSS 里再写一遍,改一处漏一处。
区块主题(Block Theme / FSE)引入了 theme.json,把「主题能用什么、默认长什么样」集中到一个 JSON 文件。编辑器读它来渲染颜色选择器、字号下拉框、间距控件;前台读它生成全局内联样式。也就是说,编辑器里能看到什么选项,完全由 theme.json 决定。理解了这一点,很多「为什么我的颜色在编辑器里选不到」的疑问就迎刃而解。
原理分析:settings 管能力,styles 管外观
theme.json 有两大块,职责分明:
| 区块 | 作用 | 类比 |
|---|---|---|
settings |
定义可用选项(调色板有哪些色、字号有哪些档) | 菜单里有什么菜 |
styles |
定义默认外观(body 背景、h2 字号、按钮圆角) | 默认端上来什么样 |
settings 里还有几个开关值得单独记:appearanceTools 为 true 时一次性打开一批 UI(边框、颜色链接、间距、排版线高);color.custom / color.defaultPalette 控制用户能否自定义颜色;spacing.spacingSizes 定义预设间距档位(WP 6.1+);useRootPaddingAwareAlignments 让根容器的 padding 与对齐(full width)正确配合,做全宽区块时必开。
版本上,version: 2 是目前最通用的写法,version: 3(WP 6.6 起)主要变化是默认关闭核心预设(defaultFontSizes、defaultSpacingSizes、defaultColorPalette 默认 false),主题需要显式声明才显示核心字号与间距。写新主题建议直接上 version 3,同时明确声明这些开关,避免升级后编辑器里「字号突然没了」。
theme.json 与 Customizer 并不冲突:区块主题里 Customizer 的「颜色」面板会被 theme.json 接管,剩余主要是「站点身份」和主题自定义项。这也是为什么新项目建议优先把视觉配置放进 theme.json。
保姆级实操
第一步:建立最小可用的 theme.json
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 3,
"settings": {
"appearanceTools": true,
"layout": {
"contentSize": "720px",
"wideSize": "1200px"
},
"useRootPaddingAwareAlignments": true
},
"styles": {
"color": {
"background": "var(--wp--preset--color--base)",
"text": "var(--wp--preset--color--contrast)"
}
}
}
layout.contentSize 与 wideSize 直接决定编辑器里「内容宽度」和「宽幅宽度」两个对齐选项的实际像素值,比在 CSS 里写 .wp-block-group 宽度可靠得多。
第二步:定义调色板
{
"settings": {
"color": {
"custom": true,
"defaultPalette": false,
"palette": [
{ "slug": "base", "color": "#ffffff", "name": "底色" },
{ "slug": "contrast", "color": "#1a1a1a", "name": "主文字" },
{ "slug": "accent", "color": "#2563eb", "name": "品牌蓝" },
{ "slug": "accent-2", "color": "#f59e0b", "name": "强调橙" },
{ "slug": "muted", "color": "#6b7280", "name": "次要文字" }
]
}
}
}
每个色值会自动生成 CSS 变量 --wp--preset--color--{slug} 和编辑器里的颜色选项,同时生成前台工具类 .has-accent-color、.has-accent-background-color。defaultPalette: false 表示不显示核心自带的那套默认色,只留主题定义的色——商业主题通常这么干,保证品牌一致性。
第三步:字号与排版
{
"settings": {
"typography": {
"fluid": true,
"fontSizes": [
{ "slug": "small", "size": "0.875rem", "name": "小" },
{ "slug": "medium", "size": "1rem", "name": "正文" },
{ "slug": "large", "size": "1.5rem", "name": "大" },
{ "slug": "x-large", "size": "2.25rem", "name": "特大" }
],
"fontFamilies": [
{
"slug": "body",
"name": "正文",
"fontFamily": "system-ui, -apple-system, \"PingFang SC\", sans-serif"
},
{
"slug": "heading",
"name": "标题",
"fontFamily": "\"Noto Serif SC\", Georgia, serif"
}
]
}
}
}
fluid: true 打开流式排版(WP 6.1+),字号会在小屏自动缩放。为中文站点配 fontFamilies 时注意中文字体体积,不建议在 theme.json 里引入 Web 字体文件,改用 wp_enqueue_style 加载并做子集化。
第四步:间距预设
{
"settings": {
"spacing": {
"defaultSpacingSizes": false,
"spacingSizes": [
{ "slug": "20", "size": "0.5rem", "name": "1" },
{ "slug": "30", "size": "1rem", "name": "2" },
{ "slug": "40", "size": "2rem", "name": "3" },
{ "slug": "50", "size": "4rem", "name": "4" },
{ "slug": "60", "size": "6rem", "name": "5" }
],
"units": [ "px", "rem", "em", "%", "vh" ]
}
},
"styles": {
"spacing": {
"padding": {
"top": "var(--wp--preset--spacing--40)",
"bottom": "var(--wp--preset--spacing--40)"
}
}
}
}
间距变量命名是 --wp--preset--spacing--{slug},slug 建议沿用核心的 20/30/40 这套数字,方便与核心区块的预设对齐。
第五步:给具体区块设默认值
{
"styles": {
"elements": {
"link": {
"color": { "text": "var(--wp--preset--color--accent)" },
":hover": { "color": { "text": "var(--wp--preset--color--accent-2)" } }
},
"button": {
"border": { "radius": "4px" },
"color": { "background": "var(--wp--preset--color--accent)" }
}
},
"blocks": {
"core/heading": {
"typography": { "fontFamily": "var(--wp--preset--font-family--heading)" }
},
"core/quote": {
"border": { "left": { "width": "4px", "color": "var(--wp--preset--color--accent)" } }
},
"core/separator": {
"color": { "text": "var(--wp--preset--color--muted)" }
}
}
}
}
elements 作用于语义元素(link、button、heading、caption),blocks 作用于具体区块类型,两者都在 styles 下。
第六步:按区块单独开关设置
{
"settings": {
"blocks": {
"core/button": {
"border": {
"customRadius": true
},
"typography": {
"fontSizes": [
{ "slug": "small", "size": "0.875rem", "name": "小按钮" }
]
}
}
}
}
}
settings.blocks 的优先级高于顶层 settings,适合给按钮单独一套字号、给图片单独关闭某些控件。
常见踩坑
- JSON 里写注释:
theme.json是标准 JSON,不支持//注释,写了会导致整个文件解析失败,编辑器回退到默认样式。 - 末尾多一个逗号:同样的后果,用编辑器的 JSON 校验或
python -m json.tool先验证。 - 改了文件前台没变化:全局样式有缓存,需要清对象缓存或更新主题版本号;开发时可用
wp theme list确认主题已启用。 defaultPalette: false后旧内容失效:文章里已使用核心颜色的区块会失去样式,迁移时要保留对应 slug 或做兼容映射。- CSS 变量引用写错:自定义属性名是
--wp--preset--color--{slug},少一个连字符就取不到值,表现为样式完全不生效。 - 案例:某站升级到 WP 6.6 后,编辑器里的字号下拉框突然只剩「自定义」,编辑们以为主题坏了。原因是 theme.json 仍是
version: 2,而新版本默认关闭了核心预设字号。把 version 改成 3 并显式加"defaultFontSizes": true,同时在typography.fontSizes里补齐主题字号,问题消失。 appearanceTools: true后编辑器选项暴增:客户嫌复杂,可改为逐项开启border、spacing、typography里的子开关。- 与
add_theme_support('editor-color-palette')混用:两者同时存在时 theme.json 优先,老代码里的声明会被忽略,清理时要一并删除。
总结
动手顺序建议:先定 layout(内容宽度)与 color(调色板),再定 typography(字号字族),然后 spacing(间距档位),最后用 styles.blocks 逐个修区块细节。写完用编辑器新建一篇文章,把每个区块都插一遍检查默认值是否符合预期——这是 区块主题开发 流程里性价比最高的一步。若项目仍以 Customizer 为主,Customizer API 添加设置项 那套依然有效,两者可以并存但不要对同一视觉属性重复配置。
