theme.json 色盤設定的進階寫法與維護策略

把品牌色寫死在 CSS 檔裡,是區塊編輯器時代最容易踩的坑。內容編輯者打開區塊側欄,看到的卻是 WordPress 預設那一排青藍、桃紅、亮橘,跟你苦心調好的品牌色完全對不上,最後不是手動填色碼填到崩潰,就是整個網站顏色花掉。theme.json 色盤設定就是用來解決這件事,它讓你把可選顏色、漸層、雙色調濾鏡集中在一個檔案裡管理,WordPress 會自動生成對應的 CSS 變數與工具類別,前台與編輯器一次同步。

多數教學停在「貼一段 palette 陣列」就結束,但真正會卡住開發者的,是區塊層級的獨立色盤、WordPress 6.6 之後的多組色盤切換、漸層引用語法,以及雙色調無法吃 CSS 變數這幾個雷。這篇會把基本結構快速帶過,重點放在這些進階寫法與維護策略上。

theme.json 的 color 物件包含哪些設定

settings.color 物件控制兩件事:哪些顏色控制項會出現在編輯器、以及使用者能從哪些預設值裡挑。它直接巢狀在最上層的 settings 底下,預設長這樣。

{
  "version": 3,
  "settings": {
    "color": {
      "background": true,
      "custom": true,
      "customDuotone": true,
      "customGradient": true,
      "defaultDuotone": true,
      "defaultGradients": true,
      "defaultPalette": true,
      "duotone": [],
      "gradients": [],
      "link": true,
      "text": true,
      "palette": []
    }
  }
}

這些設定可以分成四組功能。第一組是 background、link、text,控制編輯器裡要不要顯示背景色、連結色、文字色的選項。第二組是 custom、customDuotone、customGradient,決定使用者能不能自己用調色盤調出任意顏色。第三組是 defaultPalette、defaultDuotone、defaultGradients,控制要不要保留 WordPress 內建的那組預設值。第四組是 palette、gradients、duotone 三個陣列,這是你註冊自己品牌預設值的地方。

布林值的設定預設都是 true,把它改成 false 就是關閉該功能。陣列型的設定預設是空陣列,填進去才會出現在編輯器。先弄懂這個分組,後面所有寫法都是這四組的組合。

自訂顏色色盤怎麼寫才正確

註冊自訂色盤的位置是 settings.color.palette,它接受一個陣列,陣列裡每個顏色物件都必須有三個屬性。

  • color:合法的 CSS 顏色值,支援 Hex、rgb、rgba、hsl、hsla、顏色名稱,以及 transparent、currentColor 這類關鍵字
  • name:給人看的標籤,會出現在調色盤的提示文字裡,可被翻譯
  • slug:機器讀的唯一識別碼,用來生成 CSS 變數與類別名稱,只能用小寫英文與連字號

假設要替主題註冊基底色、對比色、主色三個顏色,寫法如下。

{
  "version": 3,
  "settings": {
    "color": {
      "palette": [
        { "slug": "base", "color": "#ffffff", "name": "基底白" },
        { "slug": "contrast", "color": "#1a1a1a", "name": "對比黑" },
        { "slug": "primary", "color": "#0b6fb8", "name": "品牌藍" }
      ]
    }
  }
}

WordPress 解析後會在 :root 生成對應的 CSS 自訂屬性,命名規則是 --wp--preset--color--{slug}。所以 primary 這個 slug 會變成 --wp--preset--color--primary,你可以在自己的 CSS 或 theme.json 的 styles 區塊裡直接引用它。

:root {
  --wp--preset--color--base: #ffffff;
  --wp--preset--color--contrast: #1a1a1a;
  --wp--preset--color--primary: #0b6fb8;
}

除了變數,WordPress 還會視情況生成工具類別。primary 這個 slug 當文字色時會有 .has-primary-color,當背景色時會有 .has-primary-background-color。這代表你在區塊編輯器裡選了某個預設色,輸出的 HTML 是掛 class 而不是寫死的行內樣式,之後改色碼只要動 theme.json 一處,全站套用該色的區塊都會跟著變。

base 與 contrast 兩個 slug 是事實標準

顏色 slug 沒有官方規定的命名規則,但 base 與 contrast 這兩個是 Twenty Twenty-Three 主題定下的事實慣例,建議照用。base 留給網站背景、contrast 留給主要文字。這樣做的好處是跨主題與外掛的相容性最高,當使用者切換到另一個也遵循這套慣例的主題時,顏色不會整個跑掉,外掛作者也能拿這組 slug 當安全的後備色。其餘像 primary、secondary、accent 就依品牌需求自由命名。

怎麼隱藏 WordPress 內建色盤只留品牌色

如果你已經把品牌色調得很精準,最不想看到的就是編輯者誤用 WordPress 內建那排亮橘亮紅。把 settings.color.defaultPalette 設成 false 就能在編輯器裡隱藏內建色盤,只剩你註冊的顏色可選。

{
  "version": 3,
  "settings": {
    "color": {
      "defaultPalette": false,
      "palette": [
        { "slug": "base", "color": "#ffffff", "name": "基底白" },
        { "slug": "primary", "color": "#0b6fb8", "name": "品牌藍" }
      ]
    }
  }
}

同理,defaultGradients 設 false 移除內建漸層,defaultDuotone 設 false 移除內建雙色調濾鏡。如果想連使用者自訂調色盤的能力都拿掉,逼大家只能從預設裡挑,再把 custom 設成 false。

這裡有個容易誤判的地方要先講清楚。就算你把 defaultPalette 設成 false,WordPress 仍然會在頁面輸出內建那十二個顏色的 CSS 自訂屬性。這不是 bug,是刻意為了向下相容,避免使用者之前在別的主題上選過的顏色因為換主題就消失。所以你檢查原始碼會看到 --wp--preset--color--vivid-red 之類的變數還在,那只是變數定義還在,調色盤的選項已經被藏起來了,兩件事不一樣。

自訂漸層的寫法與引用語法

註冊漸層的位置是 settings.color.gradients,結構跟色盤幾乎一樣,差別只在第三個屬性叫 gradient,值要放完整的 CSS 漸層語法。

  • slug:唯一識別碼
  • name:編輯器裡顯示的名稱
  • gradient:合法的 CSS 漸層值,linear-gradient、radial-gradient、conic-gradient、repeating 系列都吃
{
  "version": 3,
  "settings": {
    "color": {
      "gradients": [
        {
          "slug": "brand-sky",
          "gradient": "linear-gradient(135deg, #0b6fb8 0%, #5ec5e0 100%)",
          "name": "品牌天空"
        },
        {
          "slug": "sunset",
          "gradient": "linear-gradient(-225deg, #231557 0%, #ff1361 67%, #fff800 100%)",
          "name": "黃昏"
        }
      ]
    }
  }
}

漸層的厲害之處在於它不限定只能用兩個色標。你可以塞多個色標做出光譜效果,也可以用硬停止點(hard stop,把兩個色標的百分比設成相鄰,例如 49.9% 跟 50%)做出色塊分割而非漸變的效果。conic-gradient 還能做出色輪。這些都只是 CSS 漸層本身的能力,theme.json 只是把它包成可選預設。

生成的變數命名同樣是 --wp--preset--gradient--{slug}。引用這些預設值有兩種寫法,差別值得弄懂。在自己寫的 CSS 裡,直接用 var(--wp--preset--gradient--brand-sky)。但如果是在 theme.json 的 styles 區塊裡指定樣式,要改用 WordPress 專用的引用語法 var:preset|gradient|brand-sky。色盤同理,CSS 裡寫 var(--wp--preset--color--primary),theme.json styles 裡寫 var:preset|color|primary。混用這兩種語法是新手很常見的錯誤,theme.json 內部認的是後者那種管線符號的寫法。

雙色調濾鏡為什麼不能引用 CSS 變數

雙色調(duotone)是套在圖片上的雙色濾鏡,常用在封面區塊或圖片區塊做風格化處理,它讓使用者各選一個陰影色與一個高光色。註冊位置是 settings.color.duotone,但它的結構跟色盤、漸層不一樣,要注意。

{
  "version": 3,
  "settings": {
    "color": {
      "duotone": [
        {
          "colors": ["#0b1a2b", "#e8f4fb"],
          "slug": "brand-blue",
          "name": "品牌藍雙色調"
        }
      ]
    }
  }
}

差異在 colors 是個陣列,要放兩個顏色值,前者是陰影、後者是高光,而且這裡有個常踩的限制。雙色調只吃 Hex 與 RGB 兩種色值,不接受其他格式。更關鍵的是,雙色調定義裡不能引用 CSS 變數,也就是說你沒辦法寫 var(--wp--preset--color--primary) 去讓濾鏡跟著品牌色走,只能填寫死的色碼。

這背後的原因是雙色調的處理方式跟色盤、漸層不同。色盤與漸層會生成 CSS 自訂屬性,所以能被 var() 引用、能隨樣式變體調整;雙色調則是透過 SVG 濾鏡實作,並不會產生對應的 CSS 變數,自然也就無法用 var() 去指。實務上的後果是,當你用樣式變體切換品牌色時,色盤跟漸層會跟著換,雙色調濾鏡卻紋風不動,需要另外維護。規劃品牌一致性時要把這個限制算進去,別假設雙色調會自動跟著主色聯動。

怎麼為單一區塊設定獨立色盤

前面的色盤、漸層都註冊在 settings.color 底下,是全站通用。但有時候你只想讓某個特定區塊有不一樣的可選顏色,例如搜尋區塊用一組灰階漸層、群組區塊用品牌漸層。這就要把設定改放到 settings.blocks 底下,依區塊名稱分別指定。

{
  "version": 3,
  "settings": {
    "blocks": {
      "core/group": {
        "color": {
          "gradients": [
            {
              "slug": "brand-sky",
              "gradient": "linear-gradient(135deg, #0b6fb8 0%, #5ec5e0 100%)",
              "name": "品牌天空"
            }
          ]
        }
      },
      "core/paragraph": {
        "color": {
          "defaultPalette": false,
          "palette": [
            { "slug": "primary", "color": "#0b6fb8", "name": "品牌藍" }
          ]
        }
      }
    }
  }
}

區塊層級的色盤行為跟全站層級有個重要差別。全站色盤的 CSS 變數掛在 :root 上,區塊層級的變數則掛在該區塊的選擇器上。以上面的段落區塊為例,生成的會是 p { --wp--preset--color--primary: #0b6fb8; },作用域只限段落區塊。這個機制讓你能做到精細的權限控制,例如只允許按鈕區塊用某幾個強調色,內文段落區塊則限制在中性色裡,避免編輯者把整篇文章染成五顏六色。

WordPress 6.6 之後怎麼提供多組色盤讓使用者切換

WordPress 6.6 起,主題可以提供多組色盤讓使用者在網站編輯器的樣式側欄裡切換,使用者選定其中一組後,全站可用的顏色就會整批更新。這對需要提供深色與淺色兩套配色、或同一套主題要服務不同品牌調性的情境很實用。

機制要分兩塊理解。寫在 theme.json 裡的那組色盤是主題的預設色盤,會直接生效。額外的色盤則是用樣式變體(style variation)的形式提供,做法是在主題的 styles 資料夾裡放額外的 JSON 檔,每個檔案格式跟 theme.json 一樣,但只覆寫 settings.color.palette 這個部分,就成了一個只換色盤的全站樣式變體。

舉例來說,主檔 theme.json 定義一組淺色品牌色,再在 styles 資料夾放一個 dark.json,裡面只寫色盤的覆寫。

{
  "version": 3,
  "title": "深色品牌",
  "settings": {
    "color": {
      "palette": [
        { "slug": "base", "color": "#101418", "name": "基底深" },
        { "slug": "contrast", "color": "#f2f4f7", "name": "對比亮" },
        { "slug": "primary", "color": "#5ec5e0", "name": "品牌藍" }
      ]
    }
  }
}

關鍵在 slug 要跟主檔保持一致。因為內容區塊綁的是 slug 而不是色碼,只要 base、contrast、primary 這些 slug 不變,使用者一切換色盤變體,所有掛著這些 slug 的區塊都會自動換上新色值,不需要逐個區塊重設。這也再次說明前面強調 slug 命名一致性的理由,它是多色盤切換能無痛運作的前提。

維護品牌色盤時要注意的幾件事

把色盤集中在 theme.json 管理之後,真正影響長期維護成本的不是初次設定,而是命名與規劃的紀律。slug 一旦上線就盡量別改,因為內容區塊與既有文章都綁在 slug 上,改 slug 等於讓舊內容的顏色失效,跟改 URL 會壞反向連結是同類型的問題。色碼可以隨時調整,slug 要當成穩定的契約來對待。

語意化命名比直觀命名耐用。用 primary、secondary、accent、surface 這種依角色命名的方式,遠比用 blue、green 這種依外觀命名來得好維護,因為哪天品牌主色從藍改成綠,叫 primary 的 slug 改個色碼就好,叫 blue 的 slug 就會出現「名字叫藍色實際是綠色」的尷尬。

如果你的網站跑 WooCommerce,色盤一致性會更重要。商店頁、購物車、結帳流程裡的按鈕、標籤、提示框,只要這些區塊用的是 theme.json 註冊的預設色而非寫死色碼,調整品牌色時整條購買動線都會同步換色,不必到處翻 CSS 找哪裡漏改。這裡只談配色一致性,金流串接與付款設定是另一回事,不在本文範圍。

最後提醒,theme.json 有版本號,目前建議用 version 3。不同版本對某些屬性的預設行為有差異,動手前先確認 "version" 標對,schema 也建議在檔案頂端加上 "$schema": "https://schemas.wp.org/trunk/theme.json",編輯器才能給你即時的欄位提示與驗證,少打錯字。

把可選顏色、漸層、雙色調集中在 theme.json,本質上是把設計決策從散落的 CSS 收斂成一份可版控、可切換、會自動生成變數的單一來源。先用四組設定分清楚「顯示什麼、能自訂什麼、保留什麼預設、註冊什麼品牌值」,再依需求往區塊層級色盤與多色盤變體推進。下一步可以打開現有主題的 theme.json,把目前寫死在樣式表裡的品牌色搬進 palette,設好 base 與 contrast,關掉用不到的內建預設,光是這一步就能讓整個編輯體驗乾淨許多。

相關文章
標籤: 色盤設定, 漸層, WordPress 主題開發, theme.json, 區塊編輯器