同一個區塊主題,有人改完版面段落之間的留白整齊一致、長得像精品官網,有人則是段落忽寬忽窄、編輯器裡拉出來的間距還跟前台對不上。差別往往不在 CSS 寫得多漂亮,而在 theme.json 間距設定有沒有先把一整套「間距尺度」定義好。把這層基礎打穩,後面不管是區塊內距、區塊之間的留白,還是讓客戶在編輯器裡自己調,都有一致的依據可循。
這篇會把 theme.json 裡 settings.spacing 的每個欄位拆開講清楚:spacingScale 怎麼自動長出一套尺度、spacingSizes 怎麼手動刻、slug 為什麼用數字、v2 跟 v3 的行為差在哪,以及實際把預設套到區塊上時最容易卡住的地方。看完你應該能替自己的主題設計出一套站台共用的留白系統。
theme.json 間距設定到底管哪些東西
settings.spacing 這個物件管的是跟 margin(外距)、padding(內距)、gap(區塊間距)相關的所有全域設定。它不是直接「套樣式」,而是定義「主題提供哪些間距選項、使用者能不能調、能調哪些單位」。真正把數值套到區塊上是 styles 那一層的事。
settings.spacing 底下有這幾個屬性,先建立全貌:
blockGap:是否開啟「區塊間距」這個控制項,值可以是true、false或null,預設null。margin:是否在支援的區塊上開啟外距控制項,預設false。padding:是否開啟內距控制項,預設false。customSpacingSize:是否允許使用者自己輸入任意間距數值,預設true。spacingScale:一個設定物件,讓 WordPress 依規則自動產生一整套間距尺度。spacingSizes:一個陣列,用來手動定義每一個間距尺寸,可以覆蓋或補充spacingScale產生的結果。units:使用者輸入自訂間距時可以選的 CSS 單位清單,例如px、em、rem、vh、vw、%。
這裡先抓一個關鍵心智模型:margin、padding、blockGap 這幾個是「開關」,決定使用者在編輯器側欄看不看得到那個控制項;spacingScale 跟 spacingSizes 才是「內容」,決定那個控制項裡有哪些可選的間距級距。兩者分工不同,設定時不要混為一談。
spacingScale 怎麼自動產生一整套間距尺度
spacingScale 的用途是讓你用「一條規則」長出一整排間距,不必一個一個手寫。WordPress 預設就帶了一組七階尺度,從中間的基準值往兩側各推三階。
預設設定長這樣:
{
"version": 2,
"settings": {
"spacing": {
"spacingScale": {
"operator": "*",
"increment": 1.5,
"steps": 7,
"mediumStep": 1.5,
"unit": "rem"
}
}
}
}
逐個欄位拆解它在算什麼:
mediumStep:整套尺度的中間基準值,這裡是1.5,也就是1.5rem。整套尺度會以它為中心往兩邊長。steps:總共要產生幾階,7代表中間一階加上下各三階。operator:推算下一階用的運算子,*是相乘,+是相加。increment:每往外一階要乘上(或加上)的量,這裡是1.5。unit:整套尺度用的 CSS 單位,這裡是rem。
用乘法 * 搭配 1.5 的倍率,往大的方向會像 1.5 → 2.25 → 3.375 這樣等比放大,往小的方向則等比縮小。這種等比級數的好處是每一階之間的視覺落差感覺一致,比起自己亂填一排數字更協調。如果你想要的是等差(每階固定加同樣的量),就把 operator 換成 +。
需要更細或更粗的尺度時,直接調 steps(要幾階)和 increment(每階差多少)即可。想完全停用這套自動尺度,把 spacingScale.steps 設成 0,WordPress 就不會生成任何預設間距。
spacingSizes 怎麼手刻每一個自訂間距
當你的設計需求沒辦法用一條等比或等差規則漂亮地長出來時,就改用 spacingSizes 自己刻。它是一個物件陣列,每個物件代表一個間距尺寸,你完全掌控每一階的數值與名稱。
每個尺寸物件要定義三個屬性:
name:給使用者看的可讀名稱,會顯示在編輯器側欄,也可被翻譯成其他語言,例如「小」「中」「大」。slug:這個尺寸的識別代號,會被拿去組成 CSS 自訂屬性。size:實際的 CSS 數值,可以是1.5rem、24px這類具體值,也可以用clamp()做流體間距。
範例:
{
"version": 2,
"settings": {
"spacing": {
"spacingSizes": [
{ "name": "小", "slug": "20", "size": "0.75rem" },
{ "name": "中", "slug": "50", "size": "1.5rem" },
{ "name": "大", "slug": "80", "size": "4rem" }
]
}
}
}
要注意 spacingScale 跟 spacingSizes 同時存在時的行為,在不同 theme.json 版本下結果不一樣,這點放在後面版本差異那節細講。一個實務原則是:除非你真的要每階都精算,否則先用 spacingScale 把骨架長出來,只在少數需要插隊的位置用 spacingSizes 補幾階,會比整套手刻省事。
為什麼間距 slug 用 20、30 而不是 sm、md、lg
WordPress 自動產生的間距預設,slug 是 20、30、40、50、60、70、80 這種數字,而不是常見的 T 恤尺碼 sm、md、lg。這不是隨便取的,背後有三個設計考量,理解它能幫你避開命名上的坑。
第一、數字天生好排序。把間距從最小排到最大,數字一眼就能比大小,T 恤尺碼則沒有這種天然順序。第二、留出插隊空間。如果某天你想在「中」和「大」之間塞一個尺寸,用數字只要取 55 就插進去了,不必把整套重新命名。第三、跨主題的內容相容性。當一個從區塊圖樣庫拿來的圖樣用了某個間距 slug,而你的主題剛好沒支援那個 slug,數字制可以退而求其次對應到最接近的值;這也是為什麼整套尺度是以中間的 50(基準)為核心往兩側生成的,有一個已知的「中」基準 50,這種降級對應才能盡量準確。
換句話說,數字 slug 是為了「可維護」與「可互通」而設計的。自己手刻 spacingSizes 時,建議沿用這套數字慣例,不要改用 small、large 這類字串,免得跟核心預設或他人的圖樣對不上。
v2 與 v3 的間距行為差在哪
theme.json 的版本號會在 API 出現破壞性變更時往上跳,舊版本在新版 WordPress 裡仍會持續支援,所以你是「主動選擇」要不要升上去。間距這塊在 v2 跟 v3 之間正好有一個會咬到人的差異,跟「主題自訂間距會不會蓋掉核心預設」有關。
在 v2 裡,行為是這樣:同時設定 spacingSizes 和 spacingScale 時,WordPress 只採用 spacingSizes 的值,spacingScale 會被忽略。而當主題提供的間距 slug 跟核心預設撞名時,主題的一律覆蓋核心的。
到了 v3(WordPress 6.6 起),多了一個 settings.spacing.defaultSpacingSizes 開關,預設值是 true,行為也跟著改:
defaultSpacingSizes為true時,編輯器會顯示核心提供的預設間距(slug 為20到80),同時禁止主題用這些相同 slug 去覆蓋。defaultSpacingSizes為false時,會隱藏核心預設間距,主題才能拿這些 slug 來用自己的值。
另外在 v3 裡,spacingScale 跟 spacingSizes 不再是二選一,兩邊產生的預設會合併並依 slug 數字排序;若 slug 撞名,spacingSizes 定義的會蓋過 spacingScale 生成的那一階。這跟 v2 的「只取其一」是完全不同的邏輯。
實務上的判斷很單純:如果你的最低支援 WordPress 版本已經到 6.6,且你有自訂間距想沿用核心的數字 slug,就升到 v3 並把 defaultSpacingSizes 設成 false,行為才會貼近你原本在 v2 的預期。傳統(classic)主題則有對應的 default-spacing-sizes theme support,當你已經宣告 editor-spacing-sizes 時它會自動變成 false。
blockGap、margin、padding 三個開關怎麼設
這三個是控制「使用者在編輯器看不看得到對應控制項」的開關,跟前面的尺度內容是兩回事。其中 blockGap 最常被搞混,先把它講透。
所謂 block gap(區塊間距),指的是頁面上區塊與區塊之間的留白。在預設的流(flow)版面裡,它是用相鄰元素的 margin-top 來實作的;在 flex 或 grid 版面裡,則是用 CSS 的 gap 屬性實作。WordPress 預設會自動輸出這段 block gap 的 CSS。
blockGap 三個值的差別整理如下:
blockGap 值 |
區塊間距控制項 | WordPress 自動生成 CSS |
|---|---|---|
null(預設) |
不顯示 | 不生成 |
true |
顯示 | 生成 |
false |
不顯示 | 生成 |
留在預設的 null 通常不建議,因為它連 WordPress 自動生成的區塊間距 CSS 都一併關掉,你得自己寫 CSS 來維持版面的垂直節奏。多數情況你會想要一致的區塊間距,所以把它設成 true,讓使用者能在支援的區塊(例如貼文範本 Post Template)上看到「區塊間距」控制項:
{
"version": 2,
"settings": {
"spacing": {
"blockGap": true
}
}
}
margin 跟 padding 則單純許多,兩者預設都是 false,也就是區塊側欄不顯示外距與內距控制項。想讓使用者能調,就各自設成 true。要不要開放這兩個,取決於你想給編輯者多大的自由度:交給客戶維護的網站,有時反而會把 margin 關掉、只留 blockGap,避免版面被調亂。
把間距預設套用到區塊與留白系統
定義好尺度只是第一步,真正讓留白生效是在 styles 那一層。WordPress 會把每個間距 slug 轉成一個 CSS 自訂屬性,命名規則固定為 --wp--preset--spacing--{slug},例如 slug 是 md 就變成 --wp--preset--spacing--md,slug 是 50 就變成 --wp--preset--spacing--50。理解這個命名規則,你才知道後面怎麼引用。
最常先設的是整站的區塊間距。WordPress 預設的 block gap 大約是 24px,幾乎每個主題都會想改掉它。假設你的設計需要區塊之間預設留 2rem,在 styles.spacing.blockGap 設一個單一值即可(blockGap 只吃單一值,不像 margin、padding 可以分四邊):
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 2,
"styles": {
"spacing": {
"blockGap": "2rem"
}
}
}
要把某個間距預設套到特定區塊上,就用前面那個 CSS 自訂屬性。以下是替核心 Pullquote 區塊加上下內距、邊框寬度也借用間距預設的例子:
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 2,
"styles": {
"blocks": {
"core/pullquote": {
"border": {
"style": "solid",
"width": "var( --wp--preset--spacing--10 )"
},
"spacing": {
"padding": {
"top": "var( --wp--preset--spacing--30 )",
"bottom": "var( --wp--preset--spacing--30 )"
}
}
}
}
}
}
這裡有個值得記住的延伸用法:間距預設本質上就是 CSS 自訂屬性,所以它不限於拿來當 margin 或 padding,連邊框寬度都能引用,整個主題需要「一致的尺寸基準」的地方都能共用同一套變數。這正是「留白系統」的核心精神——不是每個區塊各填各的數字,而是大家都引用同一組級距。
設定間距時最常踩的雷與排查
有幾個坑在文件裡藏得比較深,這裡先點名,省得你卡半天:
第一、blockGap 會壓過你給標題加的上方 margin。常見需求是「標題前面多留白、標題跟下一段貼緊一點」,但你在 theme.json 給標題加的 margin-top 幾乎一定會被 blockGap 設定覆蓋掉,這種情境通常只能自己補一段 CSS。例如在 blockGap 為 2rem 的前提下,想讓標題上方有 3rem、緊接標題的下一個元素只留 1rem:
.is-layout-flow * + :is( h1, h2, h3, h4, h5, h6 ),
.wp-block-post-content * + :is( h1, h2, h3, h4, h5, h6 ) {
margin-top: 3rem;
}
.is-layout-flow :is( h1, h2, h3, h4, h5, h6 ) + *,
.wp-block-post-content :is( h1, h2, h3, h4, h5, h6 ) + * {
margin-top: 1rem;
}
這段特地把 .wp-block-post-content 也選進來,是因為文章編輯器本身不知道前台的版面長怎樣;只選一邊會造成編輯器跟前台的間距對不上。
第二、編輯器跟前台間距對不上,多半就是上面這類「前台 CSS 沒同步進編輯器」造成的,排查時先確認自訂 CSS 的選擇器有沒有同時涵蓋前台版面類別(如 .is-layout-flow)與編輯器的內容容器。
第三、改了 spacingScale 卻看不到新尺度,先確認 steps 不是 0(那會整套關掉),再確認你用的版本下 spacingSizes 有沒有把它整個取代(v2 行為)或撞名覆蓋(v3 行為)。
把這套尺度先搭好,再決定哪些開關開給編輯者,留白系統就有了一致的地基。先用 spacingScale 長出骨架、必要時用 spacingSizes 補階、依目標 WordPress 版本決定要不要升 v3 並處理 defaultSpacingSizes,最後在 styles 用 --wp--preset--spacing--{slug} 把預設套到區塊上。動手替你正在開發的主題寫下第一組 spacingScale,再回頭微調級距,會比一開始就想把每一階都算到完美來得實際。