深色模式(Dark Mode)在近幾年已從「開發者偏好」升格為主流使用者的基本期待。iOS、Android、Windows、macOS 相繼內建系統層級的深色切換,使用者只要調整一個設定,整個作業系統連帶的應用程式介面都會跟著變色。瀏覽器也不例外,Chrome、Firefox、Safari 都支援把作業系統的偏好設定傳遞給網頁,讓網頁的 CSS 接收並做出對應調整。
對 WordPress 站長來說,若主題沒有實作深色樣式,使用者在深色系桌面環境下開啟網站,看到的會是刺眼的白色介面,品牌一致性與閱讀體驗都會受損。本文以「wordpress 深色模式」的實作角度出發,從媒體查詢(media query)的原理說起,說明區塊主題與經典主題各自怎麼接上這個機制,以及 theme.json 的色盤要如何對應設定。
prefers-color-scheme 媒體查詢的運作原理
瀏覽器把作業系統的深淺色偏好,透過 CSS 媒體功能 prefers-color-scheme 暴露出來,值只有兩種,分別是 light 與 dark。寫在 @media (prefers-color-scheme: dark) { } 這個區塊裡的樣式,只有在作業系統選擇深色模式時才會生效,平時不套用,也不需要 JavaScript 介入。
這個機制屬於純 CSS 層的解法,瀏覽器在解析樣式表時就已決定是否套用,不需要等候 DOM 載入完畢後再由腳本切換類別。速度快、不影響首次渲染,也不會有樣式閃爍(Flash of Unstyled Content)的問題。
主題要支援深色模式,最基本的做法是在樣式表裡加入這個媒體查詢,然後在裡面覆寫背景色、文字色、邊框色這些對視覺衝擊最大的屬性。使用 CSS 自訂屬性(Custom Property,也就是常說的 CSS 變數)可以讓這段程式碼更簡潔,在 :root 宣告一組預設值,在媒體查詢裡只改動 :root 的變數值,其他規則不用異動。
區塊主題與經典主題的做法差異
WordPress 6.0 之後,主題生態分成兩個截然不同的路徑,深色模式的實作方式也隨之分岔。
區塊主題用 theme.json 控制色盤
區塊主題(Block Theme)的設定中心是 theme.json,全站的色彩、字體、間距都在這裡宣告,WordPress 核心會把這些宣告轉成全站通用的 CSS 自訂屬性。深色模式要在這個架構裡運作,需要兩個環節配合。
第一個環節是在 theme.json 的 settings.color.palette 宣告完整的色盤,涵蓋前景色、背景色、強調色,並確保每個色票有語意化的命名,例如 "slug": "background" 而非 "slug": "white"。語意化命名的目的,是讓深色模式只需要改變「背景」所對應的顏色值,而不是把整份色盤重寫一遍。
第二個環節是在主題的 style.css 或獨立的 CSS 檔裡,加入 prefers-color-scheme: dark 媒體查詢,覆寫 WordPress 核心生成的 CSS 自訂屬性。核心生成的屬性名稱格式固定為 --wp--preset--color--{slug},例如色盤裡 slug 為 background 的顏色,對應屬性名就是 --wp--preset--color--background。在媒體查詢裡把這組屬性改成深色值,整個區塊的背景色就會自動跟著切換。
WordPress 6.5 起,theme.json 進一步支援 styles.color 底下的條件式樣式,讓部分主題可以直接在 JSON 層宣告深色變體,不需要另開 CSS 檔。不過這個功能目前各主題的實作完整度差異頗大,直接從 CSS 媒體查詢層切入仍是最穩定的路徑。
經典主題走 CSS 媒體查詢覆寫
經典主題(Classic Theme)沒有 theme.json,樣式由 style.css 及子主題(Child Theme)的 CSS 全權管理。做法相對明確,在樣式表底部新增媒體查詢,把需要在深色下改變的屬性逐一覆寫即可。
若主題本身有用 CSS 自訂屬性,就把變數定義在 :root 裡,深色媒體查詢只改 :root 的變數值。若主題寫的是傳統的具體顏色值(例如 background-color: #ffffff),則需要逐一找到選擇器並覆寫,工作量較大,但邏輯相同。
使用子主題時,深色模式的 CSS 加在子主題的 style.css 尾端即可,不需要改動父主題,日後父主題升級也不會被覆蓋。若要讓使用者能手動切換深淺色、而非單純跟著系統走,則需要搭配 JavaScript 動態切換 <html> 或 <body> 上的 class,再在 CSS 裡同時以媒體查詢與 class 選擇器分別處理兩種情境。
theme.json 的色盤對應設定
在區塊主題的架構下,色盤設定是 wordpress 深色模式能否順暢運作的基礎,有幾個細節值得留意。
語意化的 slug 命名:色盤裡每個顏色的 slug 應對應角色而非顏色本身。background、foreground、primary、secondary 這類命名,在深色模式切換時只需要改值,不需要改結構。反過來,若用 white、black、light-gray 這類顏色名,深色模式下「--wp--preset--color--white 要顯示成深色」這種邏輯本身就不合理,後續維護難度也較高。
確認核心生成的屬性名稱:WordPress 核心把 theme.json 的 slug 轉成 CSS 屬性時,會把大寫轉小寫、空格轉連字號,不做其他轉換。建議在瀏覽器開發者工具的「元素」面板找到 <html> 標籤下的 :root 樣式,確認實際屬性名稱後再撰寫覆寫規則,避免 slug 拼寫有誤導致樣式未能套用。
圖片與媒體的處理:CSS 自訂屬性能處理的是色彩,圖片本身不在覆蓋範圍。背景圖片在深色模式下對比度可能下降,常見的處理方式是在媒體查詢裡搭配 mix-blend-mode: multiply 或 filter: brightness(0.85) 降低圖片亮度,讓頁面整體視覺保持一致。
以下是區塊主題的對應設定示意,說明 theme.json 色盤宣告與 CSS 覆寫之間的對應關係:
| theme.json slug | 核心生成的 CSS 屬性 | 深色模式建議覆寫為 |
|---|---|---|
background |
--wp--preset--color--background |
#1a1a1a 或對應深色值 |
foreground |
--wp--preset--color--foreground |
#e8e8e8 或對應淺文字色 |
primary |
--wp--preset--color--primary |
對應深色背景的強調色 |
secondary |
--wp--preset--color--secondary |
輔助強調色,注意對比度 |
對比度是深色模式最容易忽略的細節。WCAG 2.1 AA 標準要求正文文字與背景的對比度至少 4.5:1,深色背景搭配深色文字、或淺色背景搭配過亮的文字,都很容易不達標。調整完色盤後,建議以 Chrome DevTools 的輔助使用功能或線上對比度檢查工具驗證一遍,確保深色版的閱讀體驗不受影響。