多數人以為,同一個網站每一頁的段落間距、區塊留白忽寬忽窄,是佈景主題做得不夠細。表面上看像是模板品質問題,實際上剛好相反。問題不在主題不夠好,而在它給了每個人太多自由。區塊編輯器預設讓你在每一個群組、每一個按鈕的 Dimensions 面板裡,直接手動敲一個自訂數值進去。今天填 24px、明天填 30px、下週換人接手又填 28px,久了整站的間距就是一堆各自為政的數字,沒有一把共同的尺可以量。
WordPress 的區塊主題其實早就準備好對付這件事。你可以在 theme.json 裡定義一套間距設計系統,讓全站的留白只能從固定幾個預設值裡挑,而不是每次都憑手感填一個新數字。這就是所謂的區塊主題間距設計系統,把間距從「每個人各填各的」收斂成「一整套有比例、有名字的預設值」,讓網站上每一處留白都出自同一把尺。
要把這套系統做對,得先搞清楚間距亂掉的真正機制,再一步步從 theme.json 定義比例尺、把後門關上。先從問題的根源講起。
間距忽大忽小,問題出在哪?
間距會漂移,關鍵在編輯器的一個預設行為。只要佈景主題沒有先定義好一套間距比例尺,使用者就是在沒有導軌的狀況下自由填數字。在區塊編輯器裡選取任何一個支援間距的區塊,打開 Dimensions(尺寸)面板,你會看到一個可以直接輸入任意數值的欄位。這個欄位由 settings.spacing 底下的 customSpacingSize 開關控制,而它預設就是開的(true)。也就是說,開箱狀態下,每個人都能對每個區塊敲進任何一個數字,沒有任何限制。
先把「間距」這個詞在區塊主題脈絡下拆清楚,因為它其實不是一個東西,而是三種各自獨立的設定:
- blockGap(區塊間隙):容器區塊內部,一個個子區塊之間的間隔。像是群組(Group)或欄(Columns)裡,上下堆疊的段落彼此之間留多少空。
- padding(區塊內留白):一個區塊的內容跟它自身邊界之間的空間,也就是區塊往內縮的那圈留白。
- margin(區塊外距離):一個區塊跟它外面其他區塊之間的距離,是往外推開的空間。
這三種在 theme.json 的 settings.spacing 底下各有一個對應開關,而且都要你自己打開才會出現在編輯器裡。blockGap 預設是 null(等於連 CSS 都不輸出)、margin 預設是 false、padding 預設也是 false。換句話說,主題如果什麼都不設,編輯器裡的邊距與內距控制根本不會出現;但一旦你為了讓編輯者能調整而把它們打開,只要沒同時處理 customSpacingSize,就等於開放了無限制的手動輸入。
真正麻煩的地方在於 customSpacingSize 預設開啟,代表就算你貼心地準備了一組漂亮的預設值,使用者還是可以無視它、自己敲一個不在清單上的數字。這也是為什麼很多站明明用同一套主題,間距卻一頁一個樣。不是主題沒給選項,是選項旁邊那個「自己填」的入口一直開著,久了大家都習慣手動輸入。
那如果完全不去碰這些設定,WordPress 其實內建就有一套備用的間距比例尺會頂上來。
沒有比例尺時,WordPress 預設用什麼間距?
就算你的主題完全不設定間距,WordPress 也不是放你自生自滅,它內建就會生成一套 7 階的預設比例尺。這套預設以中間值往兩端展開,每一階大致以 1.5 倍的節奏遞增,對應到七個註冊好的 CSS 自訂屬性,實際數值是這樣:
| CSS 自訂屬性 | 數值 |
|---|---|
--wp--preset--spacing--20 | 0.44rem |
--wp--preset--spacing--30 | 0.67rem |
--wp--preset--spacing--40 | 1rem |
--wp--preset--spacing--50 | 1.5rem |
--wp--preset--spacing--60 | 2.25rem |
--wp--preset--spacing--70 | 3.38rem |
--wp--preset--spacing--80 | 5.06rem |
在編輯器介面裡,這七階會以一組由小到大的標籤呈現,從最小的 2X-Small、X-Small、Small、Medium,一路到 Large、X-Large、2X-Large。使用者在 Dimensions 面板拉動滑桿時,選到的其實就是這幾個預設值。
原來預設就有一套系統,只是多數人沒意識到它的存在,也沒有主動鎖定它,於是它才會被隨手敲進去的自訂數值蓋過去。間距亂掉的根源不是「沒有系統」,而是「有系統卻沒被守住」。理解了這一層,接下來要問的是,WordPress 給了哪些工具能自己定義一套比例尺、又該挑哪一種來寫。
間距比例尺(spacingScale)跟自訂尺寸(spacingSizes)該選哪一種?
WordPress 提供兩種註冊間距預設值的方式,先決定用哪一種,後面的操作才不會走冤枉路。這兩種一個是「給規則、讓它自動長出一串數列」,另一個是「一階一階手動列給它」,適用情境很不一樣。
第一種是 spacingScale(間距比例尺)。你只要給它一組規則,包含用什麼運算、遞增多少、要幾階、中間值是多少、用什麼單位,WordPress 就會照這組規則自動算出整條等比或等差數列。它的好處是設定極少、改動極快,想讓全站間距整體變密或變鬆,只要調一個參數,所有階數會一起連動。缺點是每一階的實際數值是算出來的,你沒辦法讓某一階剛好精準等於視覺稿標的那個值。
第二種是 spacingSizes(自訂尺寸)。你不給規則,而是一階一階把每個值親手列出來,每一階要標三樣東西:name(顯示名稱)、slug(識別代號)、size(實際的 CSS 值)。它的好處是每一階你說了算,可以精準對齊設計稿;而且 size 不只能填固定的 rem 值,還能填 clamp() 這種會隨視窗寬度浮動的流動值(fluid),對響應式排版特別有用。代價是要一階一階寫,改動時也得一階一階調。
那到底怎麼選?可以這樣判斷:
- 想要快、想要一次設定全站套用,而且不介意數值是自動算的 → 選
spacingScale,給一組規則讓它長出來。 - 每一階都要對齊視覺稿的精確數字,或有 fluid(隨螢幕縮放)的需求 → 選
spacingSizes,手動把每階寫死。
技術上這兩種可以並存,但官方也直言,同時用兩套通常只是自找麻煩,一般建議擇一。除非你是「用比例尺長出主幹、再額外補一兩個特殊尺寸」這種特例,否則挑定一種就好。下面各示範一次寫法。
用 spacingScale 讓比例尺自動生成
spacingScale 之所以省事,是因為它把整條數列濃縮成五個參數,你改其中一個,全部階數就跟著重算。這五個參數分別是:
- operator(運算子):決定用哪種方式遞增,
*是相乘(等比數列)、+是相加(等差數列)。預設是*。 - increment(遞增值):每一階往上乘或加的量。預設是
1.5。 - steps(階數):整條比例尺要幾階。預設是
7。 - mediumStep(中間值):整條數列的中軸,比例尺會以這個值為錨往上下兩端展開。預設是
1.5。 - unit(單位):一個合法的 CSS 間距單位,例如
px、em、rem、%等。預設是rem。
mediumStep 這個角色容易被誤解。它不是「最小階」也不是「最大階」,而是正中間那一階,系統會從這個中軸同時往小和往大兩個方向長出其餘階數。這也是為什麼調它會讓整套間距的重心一起平移。

舉一個實際例子。如果你想要一條七階、每階以相加方式遞增 0.25rem、以 1rem 當中軸的數列,theme.json 可以這樣寫:
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 2,
"settings": {
"spacing": {
"spacingScale": {
"operator": "+",
"increment": 0.25,
"steps": 7,
"mediumStep": 1,
"unit": "rem"
}
}
}
}Code language: JSON / JSON with Comments (json)
這組設定算出來的比例尺會跟 WordPress 內建那條完全不同,變成從 --20 的 0.25rem、--30 的 0.5rem、--40 的 0.75rem、--50 的 1rem,一路往上以 0.25rem 為間隔遞增到 --80 的 1.75rem。整條數列的疏密、重心,都由那五個參數決定;哪天覺得全站太鬆,把 increment 從 0.25 改小,全部階數立刻一起收緊。這種「一次設定、全站連動」正是比例尺的核心價值。
用 spacingSizes 手動列出每一階
如果你要的是每一階都精準對齊設計稿,或需要間距會隨螢幕縮放,就改用 spacingSizes 陣列,一階一階把值寫死。陣列裡每個物件填三個屬性:name(人看得懂、可翻譯的名稱)、slug(會被接到 --wp--preset--spacing--{slug} 這個 CSS 自訂屬性後面的代號)、size(實際的 CSS 值)。
要完全覆蓋掉內建的預設值,慣用做法是同時把 spacingScale.steps 設成 0,等於關掉核心自動生成的那條比例尺,只留你手寫的這幾階。下面這個例子註冊了五階,前四階是固定值、第五階用 clamp() 做成流動間距:
{
"$schema": "https://schemas.wp.org/trunk/theme.json",
"version": 2,
"settings": {
"spacing": {
"spacingScale": {
"steps": 0
},
"spacingSizes": [
{ "name": "Step 1 - Fixed", "size": "0.25rem", "slug": "10" },
{ "name": "Step 2 - Fixed", "size": "0.5rem", "slug": "20" },
{ "name": "Step 3 - Fixed", "size": "0.75rem", "slug": "30" },
{ "name": "Step 4 - Fixed", "size": "1rem", "slug": "40" },
{ "name": "Step 5 - Fluid", "size": "clamp(1.125rem, 1.25vw + 0.7rem, 1.25rem)", "slug": "50" }
]
}
}
}Code language: JSON / JSON with Comments (json)
第五階的 clamp(1.125rem, 1.25vw + 0.7rem, 1.25rem) 就是流動間距的寫法,它給間距設了一個下限(1.125rem)、一個上限(1.25rem),中間那段 1.25vw + 0.7rem 則會隨視窗寬度在上下限之間微幅縮放。螢幕窄時取偏小的值、寬時取偏大的值,卻永遠不會超出你設的範圍。比起單純寫死一個固定 rem,這種寫法讓間距在不同裝置上都保持得體,是響應式排版很實用的一招。
自訂尺寸的數量沒有硬性上限,你要幾階就寫幾階。不過有一個介面上的門檻值得記住。一旦你註冊超過七個尺寸,編輯器裡原本的滑桿就會改成下拉選單。原因很直覺。滑桿在選項太多時反而難精準拖到你要的那一階,換成下拉清單挑起來更明確。所以在決定要幾階時,七這個數字不只是慣例,也是介面體驗的一個分界。
在 theme.json 設定間距比例尺的步驟
觀念清楚之後,把它收斂成可以照做的流程。這一整節只解決一件事,讓你的網站「有一套間距系統」;至於「怎麼避免使用者又故態復萌、繼續亂填」,是下一節才要處理的閉環,這裡先把系統立起來。
大方向分成三步。第一步先在 settings.spacing 底下把要用的欄位打開(blockGap、margin、padding 視需求設成 true),第二步從 spacingScale 或 spacingSizes 選一種方式把比例尺寫進 theme.json,第三步回編輯器確認間距選單已經換成你的新比例尺。要提醒的是,theme.json 是一套分層設定,它同時餵給前台樣式和後台編輯器介面,所以你在這裡改的東西,會一次影響「網站前台長怎樣」跟「編輯者在後台看到哪些選項」兩邊。下面把三步拆開講。
步驟一:決定比例尺的基準值與階數
動手寫 JSON 之前,先做兩個設計決定:中間基準值要放在哪、整套要幾階。
基準值就是 mediumStep 那個中軸,常見的做法是以 1rem 或 1.5rem 當中心,往上往下展開。這個值決定了整套間距的「重心」在哪,也決定了小的那幾階有多小、大的那幾階有多大。
階數則決定系統的「密度」,這裡有個要拿捏的取捨。階數太少,遇到某些版面時會發現沒有剛好合用的那一格,只好將就;階數太多,選單一長,編輯者反而在一堆相近的值裡迷路,也失去了「限縮選擇」的初衷。前面提過超過七階介面會從滑桿變下拉,這也是七階常被當成預設的原因之一。實務上,把幾階分別對應到 T-shirt size 那種由小到大的命名(例如 X-Small、Small、Medium、Large、X-Large),既好記又好溝通,跟 WordPress 內建預設 2X-Small 到 2X-Large 的思路一致,是一個好用的起手參考。
步驟二:寫進 theme.json 並指定單位
決定好基準值與階數,就照前面示範的 spacingScale 或 spacingSizes 寫法,把選定的比例尺填進 theme.json 的 settings.spacing。
寫的同時要一併決定一件常被忽略的事,也就是開放哪些 CSS 單位給使用者。這由 settings.spacing.units 這個陣列控制,預設開放的是 px、em、rem、vh、vw、% 這幾種。可用的單位其實不只這些(像 vmin、vmax、ch、cm、pt 等也都合法),但單位開得越多,反而越容易讓不同人各用各的單位填出五花八門的值,讓好不容易建立的系統又鬆掉。比較穩的做法是把 units 收斂到少數幾種,例如只留 rem 一種,讓全站間距都用同一個單位講話,數值之間才好比較、好維護。
步驟三:在 Site Editor 裡確認每個區塊套用到同一組數值
設定寫好、存檔後,切回 Site Editor(站台編輯器)或區塊編輯器做最後驗收。選取幾個常用的區塊,像 Group(群組)、Columns(欄)、按鈕,分別打開它們的 Dimensions(尺寸)面板,你會看到 Padding(內距)、Margin(外距)、Block Spacing(區塊間隙)三組控制。
驗收的重點在於,這裡的滑桿或下拉選單,挑到的應該就是你剛剛在 theme.json 設定好的那組預設值,而不是要你憑空敲一個數字。從預設值裡挑,就是這整套系統要養成的操作習慣。如果某個區塊需要四邊留白不一致,可以點面板上的「Unlink sides」(解除四邊連動)圖示,把上、下、左、右拆開個別設定,但即使是個別設定,也仍然是從同一組預設值裡挑,而不是回頭手動輸入。確認過幾個代表性區塊都吃到新比例尺,這一步就算完成。
怎麼讓使用者不再亂輸入間距值?
到這裡系統已經立好了,但少了關鍵一步,前面的功夫多半會白費。原理講完、比例尺也寫進去了,接下來最容易被忽略的是,那個「自己填數字」的入口只要還開著,使用者遲早又會手動敲一個不在清單上的值進去,間距照樣會漂移。不是多加一組漂亮的預設值就夠了,而是要把後門關起來。
關後門的開關,就是前面提過、預設是開啟的 customSpacingSize。把它在 settings.spacing 底下設成 false:
{
"settings": {
"spacing": {
"customSpacingSize": false
}
}
}Code language: JSON / JSON with Comments (json)
這一設下去,編輯器裡那個讓人自由輸入任意數值的欄位就會消失,使用者只能從你定義好的預設值裡挑。想填一個不在比例尺上的數字?沒有入口了。等於把「限縮選擇」這件事從「拜託大家自律」變成「介面上根本沒得亂填」。
這對多人協作的站台特別有價值。一個站如果有好幾位編輯、好幾個作者輪流上稿,你沒辦法盯著每個人每次填的間距。把自訂輸入關掉之後,不管誰來、不管接手的人懂不懂設計,能挑的間距就是那固定幾階,全站的留白自然收斂在同一把尺上。這也讓日後交接省心,新人不必去背「我們站的段落間距要填多少」,因為選單裡本來就只有對的那幾個選項。把比例尺定好、再把 customSpacingSize 鎖上,這兩件事合起來才是完整的閉環,一個負責「有得選」、一個負責「不能亂選」。
全站套用同一套間距,Style Book 怎麼一次設定好?
比例尺定了、後門也關了,但如果每一頁、每個新區塊你都還要手動去挑那個「對的」預設值,其實還是很費工。Site Editor 裡的 Style Book(樣式書)就是用來把這最後一哩路補上的功能,它讓你不必逐頁逐區塊調整,而是直接對某個「區塊類型」設一次預設留白,全站所有這類區塊就都吃到同一組值。
操作上,打開 Style Book 後,你可以瀏覽到各種區塊類型,像 Buttons(按鈕)、Media & Text(媒體與文字)、主要內容區域等等,點進某一類,直接為它設定預設的 Padding、Margin、Block Spacing。設好之後,全站往後新增的這類區塊,一出生就帶著這組留白,不用任何人再手動去挑。
這一步的意義,是把間距系統從「有得選」再往前推一格,變成「預設就是對的」。前面幾節解決的是「使用者選間距時,只能從固定幾階裡挑」;Style Book 解決的則是「使用者根本不必選,因為每個區塊類型的預設值本來就對」。兩者疊起來,全站間距的一致性才真正靠系統撐著,而不是靠每個人每次都記得挑對。
theme.json 第 3 版之後,間距預設值的合併規則變了什麼?
系統、後門、預設值都設定好之後,還有一個版本相關的坑要特別提醒。如果你參考的是舊教學、卻在新版 WordPress 上寫設定,間距選項可能會出現非預期的重複或消失。原因是 theme.json 從 WordPress 6.6 起進入 version 3,而 v3 改了 spacingScale 與 spacingSizes 的合併規則,跟 v2 的行為不一樣。
先講 v2。在 version 2 的 theme.json 裡,如果 spacingScale 跟 spacingSizes 同時存在,WordPress 只認 spacingSizes,spacingScale 會被整個忽略掉。所以舊教學才會教你「用 spacingSizes 時,順手把 spacingScale.steps 設成 0」,因為當時不設也沒差,反正比例尺會被無視。
到了 v3,規則變了。現在兩者不再是二選一,而是會被合併在一起,並依 slug 的數字大小重新排序;只有當兩邊出現相同的 slug 時,spacingSizes 裡定義的那一階才會覆蓋掉 spacingScale 生成的同 slug 值。這代表如果你照舊版習慣同時留著兩套、又沒清乾淨,v3 會把它們併起來,很可能長出一堆你沒預期的間距選項。
v3 還多了一個叫 defaultSpacingSizes 的開關,用來決定要不要保留 WordPress 內建那組預設 slug(20、30、40、50、60、70、80)。它預設是 true,也就是編輯器裡會照樣顯示核心那七階預設。但代價是,當它為 true 時,你的主題不能佔用這些預設 slug;要用自己的預設完全取代掉那組內建 slug,就得把 defaultSpacingSizes 設成 false。
所以從 v2 升級到 v3、又想維持原本「只用我自己那套間距」的行為,調整方向有兩處。一是把 defaultSpacingSizes 設成 false(不然核心那七階會跟你的併在一起冒出來),二是把舊版那個為了關掉預設而寫的 spacingScale: { "steps": 0 } 拿掉,在 v3 裡改用 defaultSpacingSizes: false 來達到同樣目的,語意更清楚也不會誤觸新的合併邏輯。沒注意這個版本差異、直接把 v2 的寫法搬到 v3,就是那些「間距選項莫名多出一排或整個消失」的常見原因。
順帶一提,這也是為什麼像 Rich Tabor 這類長期做主題的人會強調,預設值的 slug 最好用標準化的整數(20、30、40…)。因為 slug 一旦跨主題統一,使用者把某段內容標成間距 20 之後改用別的主題,那段內容至少還會套到新主題裡的 20 那一階,而不是整個掉光;反之若每個主題各用各的命名,換主題時內容的間距就對不上了。把 slug 標準化,等於讓你的間距系統不只在這個站內部一致,連跨主題搬遷時都還撐得住。
間距會亂,從來不是佈景主題不夠好,而是網站從一開始就沒有一套間距設計系統可循,只能靠每個人的手感各填各的。把 spacingScale 或 spacingSizes 定下來、把 customSpacingSize 鎖起來、再用 Style Book 把每個區塊類型的預設值一次設好,這是一次性的工程,換來的卻是往後每一頁、每個新區塊都不必再猜「間距該填多少」。把這套系統做對,之後不管是自己維護,還是哪天交給別人接手,整個站都能用同一把尺、同一種語言講間距這件事。
