這個新章節要介紹主題樣式,但我一邊查資料一邊寫,卻越寫越不對勁——寫的方向跟實作內容對不上,所以想先釐清這章要談什麼。
一般談到主題樣式,多半是指深色/淺色模式,但我想分享的比較偏向遊戲的主題設定。切換主題時,會改變的內容包含:色系、圖片色系、角色服裝、裝飾圖案。不過我本身也有點好奇色彩模式是怎麼實作的,而且說實在,這才是 Web 開發比較常遇到的需求。😂
所以今天會先研究色彩模式的寫法,再參考 Bootstrap 的做法,回頭思考為什麼要用 SCSS。那麼我們開始吧!
首先,來看看專案的主題樣式有哪些要注意的地方:
這樣看來,規劃主題樣式時,程式碼要保持可擴充性。並且顏色設定最好集中,方便管理。
有下面幾種做法,如果要讓使用者手動切換主題,還需要搭配 JS 來操作。
@media (prefers-color-scheme: dark):利用媒體查詢系統的色彩設定,設定對應的網頁色系。但是使用者不能在網頁上切換。
color-scheme 搭配 light-dark() 函式:讓 CSS 屬性能設定兩種顏色。寫法最簡潔,但只能有 light 與 dark 兩種主題。
/* 啟用 light-dark(),值固定是 light dark */
:root {
color-scheme: light dark;
}
body {
color: light-dark(#333333, #ffffff);
background-color: light-dark(#ffffff, #1a1a1a);
}
CSS 變數搭配 HTML 元素的 data- 屬性: [data-theme="..."] 覆寫 CSS 變數,彈性度高。
:root,
[data-theme="light"] {
--bg: #ffffff;
--text: #333333;
color-scheme: light; /* 改變捲軸、表單元素 */
}
[data-theme="dark"] {
--bg: #1a1a1a;
--text: #ffffff;
color-scheme: dark;
}
body {
background: var(--bg);
color: var(--text);
}
💡 混用:利用
light-dark()定義變數,例如--bg: light-dark(#fff, #1a1a1a),同時保留[data-theme]用來手動切換。
可以看到,如果要做一般的顏色模式, CSS 變數的寫法最符合需求。它能設定複數色彩模式外,顏色設定還集中在主題區塊。
Bootstrap 的色彩模式是使用 data-bs-theme 屬性,在目標區塊的父層加上這個屬性,就能向下繼承色彩模式(放在 <html> 元素就是全站套用)。F12 開啟開發人員工具,我們可以看到色彩設定的方式其實與 [data-theme="..."] 相同。

不過,Bootstrap 還有一個我想要參考的點,那就是 Bootstrap 主題色設定的方法。在 Bootstrap 中為什麼可以只在 _variables.scss 新增一個顏色,就能產生出一組衍生樣式呢?
能簡單分成幾個步驟:
_variables.scss 新增一個基礎色的變數
$milk-tea: #a0714f;
tint-color()、shade-color()、 shift-color() 等函式,換算出衍生色。_variables.scss 的主題色 map 中,新增對應名稱與要套用的變數。
$theme-colors: (
"primary": $primary,
"secondary": $secondary,
// ...
"milk-tea": $milk-tea,
);
.scss 讀取主題色 map,再跑一次迴圈產生對應的主題 class。這個專案不需要像 Bootstrap 那樣,從一個顏色延伸出整套 UI 元件系統。
我預計用一組帶有 theme 前綴的 class,來套用色彩變數。但還是希望有個色彩 map 能讓開發者快速了解主題顏色設定,並且能用這個 map 產出主題 CSS 變數與通用主題樣式。
回到開頭的問題:既然 CSS 變數已經能切換主題,為什麼還需要 SCSS?因為兩者負責的事情不同:
data-theme,變數就會被覆寫。至於圖片色系、角色服裝這類需要圖片的主題元件,會在後續章節另外介紹。
今天比較像是行前說明,先了解要做什麼、怎麼做比較好後,再進入正題。
明天會介紹如何用 SCSS 管理色票!