這個網站支援深色與淺色主題,但整份樣式表裡沒有第二套區塊樣式,也沒有任何 JavaScript 切換邏輯。秘密只有一個:所有顏色都不直接寫死,而是引用 CSS 變數;深淺色只是兩組變數值。
抽變數的方法
在 :root 定義一組語意化的變數:--bg、--text、--accent、--card-surface、--card-shadow 等等,預設值是深色。接著用 @media (prefers-color-scheme: light) 把同一組變數覆寫成淺色值。所有區塊樣式一律寫 var(--*),於是「換主題」這件事從改幾百行樣式,變成改十幾個變數。
命名是成敗關鍵
變數要用「語意」命名而不是「顏色」命名。--card-surface 在深色模式可以是深灰漸層、淺色模式是白色——名字都成立;但如果叫 --dark-gray,淺色模式一覆寫就變成謊言。語意化命名讓變數成為設計系統的詞彙表,之後加新區塊時只要選對詞,深淺色自動都對。
魔鬼藏在細節裡
幾個容易漏掉的地方:在 :root 設 color-scheme: dark light,瀏覽器的原生元件(捲軸、表單控制項)才會跟著切換;HTML 的 theme-color meta 標籤可以帶 media 屬性,讓手機瀏覽器的網址列顏色也跟著主題走;陰影與光暈在淺色背景上需要不同的透明度,所以連 --card-shadow 這種看似萬年不變的東西也要抽成變數。
為什麼不做手動切換鈕
跟隨系統設定對多數個人網站是更好的預設:使用者已經在作業系統層面表達過偏好,尊重它就好。真的需要手動切換時,這套架構也只要把變數組掛在一個 data attribute 上、用幾行 JS 切換 attribute 即可——變數層完全不用動。
把顏色抽成變數是那種「做的時候多花一小時、之後每次改版都省一天」的投資。如果你正要開新專案,從第一行 CSS 就這樣寫吧。
Max Chu