theme.json 結構解析——settings、styles 與覆寫順序

第一次打開一個區塊主題的 theme.json,畫面往往是密密麻麻的巢狀大括號。settings 裡有 colorstyles 裡也有 colorsettings 底下有 blocksstyles 底下又有一個 blocks。看起來重複,實際上每一層各司其職。搞懂 theme.json 結構解析的關鍵,不是把每個欄位背起來,而是先看懂它「分成哪幾塊、哪一塊管什麼、誰會蓋過誰」。

這篇把 theme.json 的頂層骨架、settingsstyles 兩大區的對應關係、以及最容易出錯的覆寫順序拆開來講。讀完你應該能拿起任何一份 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 的檔名)、areaheaderfootersidebaruncategorized),可選 title
  • patterns:宣告要從官方圖樣目錄綁進主題的區塊圖樣。

其中 settingsstyles 是日常維護動最多的兩塊,也是整份檔案的主體。理解 theme.json 結構,本質上就是理解這兩個區的內部分工與彼此呼應。

要補充一點:即使 theme.json 接管了視覺樣式,主題根目錄仍然必須保留一個 style.css。WordPress 靠它檔頭的註解(Theme Name、Author、Version)來辨識主題,後台才看得到這個主題。檔案裡的 CSS 規則可以完全清空,但檔案本身不能少。

settings 區負責定義可用的選項與預設值

settings 是主題的「規則欄杆」。它不直接畫出任何顏色或字級,而是宣告「使用者在編輯器裡能拿到哪些選擇、哪些功能要開、哪些要關」。對交付給客戶的網站來說,這一區是防止版面被改亂的主要工具。

常見的子物件包括:

  • colorpalette 定義調色盤(每個顏色一組 slugcolorname),gradients 定義漸層預設,duotone 定義雙色調。把 custom 設成 false 會關掉自訂顏色選擇器,使用者就只能用你定義的品牌色。defaultPalette 控制要不要顯示核心內建的調色盤。
  • typographyfontFamilies 定義字體家族,fontSizes 定義字級預設。customFontSizefalse 會收掉自訂字級的輸入框。fluid 開啟流動式字級。
  • spacingspacingSizesspacingScale 定義間距級距,units 限制可用的單位(pxemrem% 等),paddingmarginblockGap 控制是否開放對應的間距調整。
  • layoutcontentSize 是內容區的預設寬度(例如 800px),wideSize 是寬版對齊的寬度(例如 1200px)。這兩個值決定了「對齊寬度」與「對齊全寬」之間的差別。
  • borderdimensionsposition:分別管邊框、最小高度、黏性定位等較新的設定。

如果你嫌一個個開太瑣碎,settings 頂層有一個 appearanceTools 開關。設成 true 等於一次打開一整組常用能力:邊框(顏色、圓角、樣式、寬度)、color.linkdimensions.minHeightposition.sticky、間距(blockGapmarginpadding)以及 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 第一層的 colortypographyspacing,套用到 <body>,是整站的基準。例如把背景設成 var(--wp--preset--color--primary)、基礎字級設成預設值、行高設 1.6
  • elements:針對 HTML 元素層級套樣式,會橫跨所有渲染該元素的區塊。最常用的是 link(連結色、:hover 狀態、底線)以及 h1h6 標題。它的好處是「一次設定、處處生效」,符合設計系統的思維,例如所有連結都用同一個次要色。
  • blocks:針對個別區塊類型覆寫。例如把所有按鈕(core/button)的圓角設成 50px、背景換成次要色;把程式碼區塊(core/code)的字體換成等寬字。

引用 settings 產生的變數是 styles 的標準寫法。與其在 styles 裡直接寫死 hex 值,不如寫 var(--wp--preset--color--secondary),這樣設定與套用之間就維持單一資料來源,改色只動 settings 一處。

這裡也帶出一個常被混淆的分界:elementsblocks 不一樣。elements.link 影響「所有」渲染成 <a> 的地方,不論它在段落、清單還是按鈕裡;blocks.core/button 只影響按鈕區塊本身。需要跨區塊統一某個 HTML 元素的外觀,用 elements;只想動某一種區塊,用 blocks

settings.blocks 與 styles.blocks 為什麼長得幾乎一樣

settings 底下有一個 blocksstyles 底下也有一個 blocks,兩者結構高度相似,這是初學者最容易看花眼的地方。它們的關係其實很單純:全域設定的縮小版,套到單一區塊上

settings.blocks 讓你針對某個區塊「另外開放或關閉某些選項」。例如全站不開放自訂顏色,但你想讓段落區塊(core/paragraph)多一組紅色可選,就在 settings.blocks["core/paragraph"].color.palette 裡單獨加進去。WordPress 會把這組顏色變數掛在 .wp-block-paragraph 這個選擇器上,而不是全站的 body

styles.blocks 則是針對某個區塊「直接套上實際樣式」,就是前一節提到的按鈕圓角、程式碼字體那類設定。

兩者的對應關係可以這樣記:

settings.blocks
開放/關閉
該區塊的選項

決定「能不能調」
styles.blocks
套上該區塊的
實際外觀

決定「長什麼樣」

整份 theme.json 的對稱性就在這裡:settings 管能力、styles 管外觀;兩者都各有一個全域層與一個 blocks 區塊層。看懂這個四宮格,巢狀結構就不再像迷宮。

theme.json 的樣式覆寫順序由低到高怎麼排

樣式到底誰蓋過誰,是 theme.json 結構裡最關鍵也最容易誤判的一段。WordPress 把樣式分成數個層級,每一層的優先權都高於前一層。從低到高依序是:

WordPress
核心預設

最低
主題的
theme.json

蓋過核心
使用者
全域樣式

蓋過主題
區塊上
手動樣式

最高

逐層拆開來看:

  • 第一層、WordPress 核心預設:核心自帶一份 theme.json,裡頭放了所有欄位的預設值。沒有任何主題或使用者設定時,畫面就靠這層撐著。
  • 第二層、主題的 theme.json:你寫的這份檔案,會逐項覆寫核心的對應預設值。沒寫到的欄位仍沿用核心預設。
  • 第三層、使用者全域樣式:使用者在 Site Editor 的「樣式」面板裡調的東西,會產生一份「使用者層級的 theme.json」,優先權高於主題。這也是為什麼客戶在後台調了顏色之後,會蓋掉你在主題裡設的預設。這一層只對區塊主題有效,因為只有區塊主題才開放 Site Editor 編輯全域樣式。
  • 第四層、區塊上手動套的樣式:在編輯器裡單獨選取某個區塊、直接在側欄調的樣式(包含寫死在區塊範本 HTML 標記裡的樣式),優先權最高,會蓋過上面所有層。

值得注意的是,全域樣式(第三層)本身的 CSS 具體度其實很低,所以單一區塊上手動設的樣式(第四層)才能輕鬆蓋過它。這個設計是刻意的:全域樣式管的是「整體基調」,個別區塊管的是「局部例外」,局部本來就該贏過整體。

這套順序不只決定前端輸出,也決定值的解析方式。當客製區塊用 useSettings 這個 hook 去讀某個設定時,WordPress 是「由高到低」反過來找:先看使用者層有沒有定義,再看區塊層、接著全域層,全都沒有才回到核心預設。輸出時由低到高疊、讀取時由高到低找,是同一條鏈的兩個方向。

theme.json 版本升到 v3 後哪些結構行為變了

如果你接手的是一份舊主題,或正準備把 version2 調到 3,有幾個影響「結構行為」的破壞性變更必須先知道,否則升版後字級或間距會默默跑掉。

v3 最核心的變更是:主題自訂的預設不再自動覆蓋核心預設,行為改成跟其他 theme.json 預設一致,要靠新的開關明確控制。具體落在字級與間距兩處。

  • settings.typography.defaultFontSizes:v3 新增的開關,控制核心內建字級(slug 為 smallmediumlargex-large)是否顯示與使用。設 true(區塊主題的預設值)會顯示核心字級,並「禁止」你的主題用相同 slug 建立預設;設 false 會隱藏核心字級,並「允許」你的主題沿用這些 slug。換句話說,v3 之後你無法再直接覆蓋核心字級,想重用 small 這類 slug,就得先把 defaultFontSizes 關掉。
  • settings.spacing.defaultSpacingSizes:與字級同理,控制核心內建間距(slug 為 20304050607080)是否顯示與使用,預設也是 true
  • spacingSizesspacingScale 的合併規則:v3 把這兩個來源「合併」起來,依 slug 數值排序;slug 相同時,spacingSizes 定義的會蓋過 spacingScale 產生的。而在 v2,同時設這兩個只會採用 spacingSizes、忽略 spacingScale

要讓 v3 維持接近 v2 的行為,做法很直接:如果你完全沒定義 fontSizesdefaultFontSizes 可以留空或設 true;如果你有定義自己的 fontSizes,就把 defaultFontSizes 設成 false,間距同理。經典主題也有對應的 theme support(default-font-sizesdefault-spacing-sizes),預設同樣是 true,但定義了 editor-font-sizeseditor-spacing-sizes 時會自動轉成 false

升版前後若發現某些字級或間距預設消失或重複,先回頭檢查這兩個 default* 開關,多半就是癥結。

拿到一份 theme.json,該怎麼按結構讀懂它

回到最開始的問題。面對一份陌生的 theme.json,不必從第一行硬讀到最後一行,按結構分層掃描會快得多。

先看頂層有哪幾個鍵,確認 version 是 2 還是 3(這決定了字級與間距的覆蓋行為)。接著把 settingsstyles 分開看:settings 回答「這個主題開放了哪些調整、定義了哪些預設」,styles 回答「實際套了什麼外觀」。每一區再分全域層與 blocks 區塊層,全域管基調、blocks 管個別區塊的例外。styles 裡多看一個 elements,它跨區塊統一 HTML 元素的樣式。

遇到樣式對不上預期時,把覆寫順序那條鏈拿出來對:核心預設、主題、使用者全域樣式、區塊手動樣式,由低到高。十之八九的「我明明設了卻沒生效」,都是被更高一層蓋掉了,尤其是客戶在 Site Editor 動過的全域樣式。把這幾個分層內化成讀檔的習慣,theme.json 就從一團大括號變成一張條理分明的設定表,要改哪裡、改了會影響誰,一眼就能定位。

相關文章
標籤: 區塊主題, theme.json, 全域樣式, 全站編輯, WordPress 主題開發