第一次打開一個區塊主題的 theme.json,畫面往往是密密麻麻的巢狀大括號。settings 裡有 color,styles 裡也有 color;settings 底下有 blocks,styles 底下又有一個 blocks。看起來重複,實際上每一層各司其職。搞懂 theme.json 結構解析的關鍵,不是把每個欄位背起來,而是先看懂它「分成哪幾塊、哪一塊管什麼、誰會蓋過誰」。
這篇把 theme.json 的頂層骨架、settings 與 styles 兩大區的對應關係、以及最容易出錯的覆寫順序拆開來講。讀完你應該能拿起任何一份 theme.json,指著某個欄位說出它在整份檔案裡的位置與作用,也知道為什麼自己在 Site Editor 裡調的顏色會蓋過主題預設、而區塊上手動設的樣式又會蓋過 Site Editor。
theme.json 的頂層結構由哪幾個區塊組成
theme.json 最外層是一個 JSON 物件,攤平來看只有幾個固定的頂層鍵。把這幾個鍵的職責記住,後面所有的巢狀內容都能歸位。
$schema:指向 WordPress 官方的結構描述檔,例如https://schemas.wp.org/trunk/theme.json。它不影響網站輸出,純粹是給編輯器用的。在 VS Code 這類支援 JSON Schema 的編輯器裡,加了這行就能取得自動完成與即時錯誤提示,少打錯一個層級。trunk可以換成特定版本,例如https://schemas.wp.org/wp/6.5/theme.json。version:API 版本號。目前區塊主題建議用3(最低支援版本到 WordPress 6.6 時更新最妥當)。版本號的作用是讓你「主動選擇」是否接受破壞性變更,舊版本在新的 WordPress 裡仍會被支援。settings:定義「有哪些選項可用、預設值是什麼」。調色盤、字級、間距級距、版面寬度、要不要開放使用者自訂顏色,都在這裡。styles:把實際的值「套上去」。網站背景色、基礎字體、連結顏色、各區塊的外觀,都在這裡決定。customTemplates:註冊主題提供的自訂範本(例如全寬頁範本),對應templates/資料夾裡的 HTML 檔。templateParts:登錄可重複使用的範本零件,例如頁首、頁尾、側邊欄。每一筆有name(不含.html的檔名)、area(header、footer、sidebar或uncategorized),可選title。patterns:宣告要從官方圖樣目錄綁進主題的區塊圖樣。
其中 settings 與 styles 是日常維護動最多的兩塊,也是整份檔案的主體。理解 theme.json 結構,本質上就是理解這兩個區的內部分工與彼此呼應。
要補充一點:即使 theme.json 接管了視覺樣式,主題根目錄仍然必須保留一個 style.css。WordPress 靠它檔頭的註解(Theme Name、Author、Version)來辨識主題,後台才看得到這個主題。檔案裡的 CSS 規則可以完全清空,但檔案本身不能少。
settings 區負責定義可用的選項與預設值
settings 是主題的「規則欄杆」。它不直接畫出任何顏色或字級,而是宣告「使用者在編輯器裡能拿到哪些選擇、哪些功能要開、哪些要關」。對交付給客戶的網站來說,這一區是防止版面被改亂的主要工具。
常見的子物件包括:
color:palette定義調色盤(每個顏色一組slug、color、name),gradients定義漸層預設,duotone定義雙色調。把custom設成false會關掉自訂顏色選擇器,使用者就只能用你定義的品牌色。defaultPalette控制要不要顯示核心內建的調色盤。typography:fontFamilies定義字體家族,fontSizes定義字級預設。customFontSize設false會收掉自訂字級的輸入框。fluid開啟流動式字級。spacing:spacingSizes或spacingScale定義間距級距,units限制可用的單位(px、em、rem、%等),padding、margin、blockGap控制是否開放對應的間距調整。layout:contentSize是內容區的預設寬度(例如800px),wideSize是寬版對齊的寬度(例如1200px)。這兩個值決定了「對齊寬度」與「對齊全寬」之間的差別。border、dimensions、position:分別管邊框、最小高度、黏性定位等較新的設定。
如果你嫌一個個開太瑣碎,settings 頂層有一個 appearanceTools 開關。設成 true 等於一次打開一整組常用能力:邊框(顏色、圓角、樣式、寬度)、color.link、dimensions.minHeight、position.sticky、間距(blockGap、margin、padding)以及 typography.lineHeight。它是個方便的起手點,開了之後再針對個別項目選擇性關閉即可。
settings 真正的價值在於「設定即生成」。當你在 palette 裡放一個 slug 為 primary 的顏色,WordPress 會自動產生一個 CSS 自訂屬性 --wp--preset--color--primary,掛在 body 上。後面 styles 區、區塊標記、甚至客製區塊的程式碼,都能引用這個變數。改一次調色盤的 hex 值,全站引用該變數的地方一起更新,不必逐處改。
styles 區負責把實際樣式套用到頁面
styles 區是 theme.json 真正「畫出畫面」的地方,等於接手了傳統 style.css 裡的全域預設樣式。WordPress 渲染頁面時讀這個 JSON 物件,自動產生對應的 CSS 變數與規則,不必你手寫選擇器。
styles 的內部結構刻意模仿 CSS 的層疊邏輯,由外而內分成三層粒度:
- 根層級(root):直接寫在
styles第一層的color、typography、spacing,套用到<body>,是整站的基準。例如把背景設成var(--wp--preset--color--primary)、基礎字級設成預設值、行高設1.6。 elements:針對 HTML 元素層級套樣式,會橫跨所有渲染該元素的區塊。最常用的是link(連結色、:hover狀態、底線)以及h1到h6標題。它的好處是「一次設定、處處生效」,符合設計系統的思維,例如所有連結都用同一個次要色。blocks:針對個別區塊類型覆寫。例如把所有按鈕(core/button)的圓角設成50px、背景換成次要色;把程式碼區塊(core/code)的字體換成等寬字。
引用 settings 產生的變數是 styles 的標準寫法。與其在 styles 裡直接寫死 hex 值,不如寫 var(--wp--preset--color--secondary),這樣設定與套用之間就維持單一資料來源,改色只動 settings 一處。
這裡也帶出一個常被混淆的分界:elements 與 blocks 不一樣。elements.link 影響「所有」渲染成 <a> 的地方,不論它在段落、清單還是按鈕裡;blocks.core/button 只影響按鈕區塊本身。需要跨區塊統一某個 HTML 元素的外觀,用 elements;只想動某一種區塊,用 blocks。
settings.blocks 與 styles.blocks 為什麼長得幾乎一樣
settings 底下有一個 blocks,styles 底下也有一個 blocks,兩者結構高度相似,這是初學者最容易看花眼的地方。它們的關係其實很單純:全域設定的縮小版,套到單一區塊上。
settings.blocks 讓你針對某個區塊「另外開放或關閉某些選項」。例如全站不開放自訂顏色,但你想讓段落區塊(core/paragraph)多一組紅色可選,就在 settings.blocks["core/paragraph"].color.palette 裡單獨加進去。WordPress 會把這組顏色變數掛在 .wp-block-paragraph 這個選擇器上,而不是全站的 body。
styles.blocks 則是針對某個區塊「直接套上實際樣式」,就是前一節提到的按鈕圓角、程式碼字體那類設定。
兩者的對應關係可以這樣記:
開放/關閉
該區塊的選項
決定「能不能調」
套上該區塊的
實際外觀
決定「長什麼樣」
整份 theme.json 的對稱性就在這裡:settings 管能力、styles 管外觀;兩者都各有一個全域層與一個 blocks 區塊層。看懂這個四宮格,巢狀結構就不再像迷宮。
theme.json 的樣式覆寫順序由低到高怎麼排
樣式到底誰蓋過誰,是 theme.json 結構裡最關鍵也最容易誤判的一段。WordPress 把樣式分成數個層級,每一層的優先權都高於前一層。從低到高依序是:
核心預設
最低
theme.json
蓋過核心
全域樣式
蓋過主題
手動樣式
最高
逐層拆開來看:
- 第一層、WordPress 核心預設:核心自帶一份 theme.json,裡頭放了所有欄位的預設值。沒有任何主題或使用者設定時,畫面就靠這層撐著。
- 第二層、主題的 theme.json:你寫的這份檔案,會逐項覆寫核心的對應預設值。沒寫到的欄位仍沿用核心預設。
- 第三層、使用者全域樣式:使用者在 Site Editor 的「樣式」面板裡調的東西,會產生一份「使用者層級的 theme.json」,優先權高於主題。這也是為什麼客戶在後台調了顏色之後,會蓋掉你在主題裡設的預設。這一層只對區塊主題有效,因為只有區塊主題才開放 Site Editor 編輯全域樣式。
- 第四層、區塊上手動套的樣式:在編輯器裡單獨選取某個區塊、直接在側欄調的樣式(包含寫死在區塊範本 HTML 標記裡的樣式),優先權最高,會蓋過上面所有層。
值得注意的是,全域樣式(第三層)本身的 CSS 具體度其實很低,所以單一區塊上手動設的樣式(第四層)才能輕鬆蓋過它。這個設計是刻意的:全域樣式管的是「整體基調」,個別區塊管的是「局部例外」,局部本來就該贏過整體。
這套順序不只決定前端輸出,也決定值的解析方式。當客製區塊用 useSettings 這個 hook 去讀某個設定時,WordPress 是「由高到低」反過來找:先看使用者層有沒有定義,再看區塊層、接著全域層,全都沒有才回到核心預設。輸出時由低到高疊、讀取時由高到低找,是同一條鏈的兩個方向。
theme.json 版本升到 v3 後哪些結構行為變了
如果你接手的是一份舊主題,或正準備把 version 從 2 調到 3,有幾個影響「結構行為」的破壞性變更必須先知道,否則升版後字級或間距會默默跑掉。
v3 最核心的變更是:主題自訂的預設不再自動覆蓋核心預設,行為改成跟其他 theme.json 預設一致,要靠新的開關明確控制。具體落在字級與間距兩處。
settings.typography.defaultFontSizes:v3 新增的開關,控制核心內建字級(slug 為small、medium、large、x-large)是否顯示與使用。設true(區塊主題的預設值)會顯示核心字級,並「禁止」你的主題用相同 slug 建立預設;設false會隱藏核心字級,並「允許」你的主題沿用這些 slug。換句話說,v3 之後你無法再直接覆蓋核心字級,想重用small這類 slug,就得先把defaultFontSizes關掉。settings.spacing.defaultSpacingSizes:與字級同理,控制核心內建間距(slug 為20、30、40、50、60、70、80)是否顯示與使用,預設也是true。spacingSizes與spacingScale的合併規則:v3 把這兩個來源「合併」起來,依 slug 數值排序;slug 相同時,spacingSizes定義的會蓋過spacingScale產生的。而在 v2,同時設這兩個只會採用spacingSizes、忽略spacingScale。
要讓 v3 維持接近 v2 的行為,做法很直接:如果你完全沒定義 fontSizes,defaultFontSizes 可以留空或設 true;如果你有定義自己的 fontSizes,就把 defaultFontSizes 設成 false,間距同理。經典主題也有對應的 theme support(default-font-sizes、default-spacing-sizes),預設同樣是 true,但定義了 editor-font-sizes 或 editor-spacing-sizes 時會自動轉成 false。
升版前後若發現某些字級或間距預設消失或重複,先回頭檢查這兩個 default* 開關,多半就是癥結。
拿到一份 theme.json,該怎麼按結構讀懂它
回到最開始的問題。面對一份陌生的 theme.json,不必從第一行硬讀到最後一行,按結構分層掃描會快得多。
先看頂層有哪幾個鍵,確認 version 是 2 還是 3(這決定了字級與間距的覆蓋行為)。接著把 settings 與 styles 分開看:settings 回答「這個主題開放了哪些調整、定義了哪些預設」,styles 回答「實際套了什麼外觀」。每一區再分全域層與 blocks 區塊層,全域管基調、blocks 管個別區塊的例外。styles 裡多看一個 elements,它跨區塊統一 HTML 元素的樣式。
遇到樣式對不上預期時,把覆寫順序那條鏈拿出來對:核心預設、主題、使用者全域樣式、區塊手動樣式,由低到高。十之八九的「我明明設了卻沒生效」,都是被更高一層蓋掉了,尤其是客戶在 Site Editor 動過的全域樣式。把這幾個分層內化成讀檔的習慣,theme.json 就從一團大括號變成一張條理分明的設定表,要改哪裡、改了會影響誰,一眼就能定位。