iT邦幫忙

2026 iThome 鐵人賽

DAY 12
0
Modern Web

從實務需求出發:前端視覺與 UI 互動開發實踐系列 第 12 篇

【Day 12】主題樣式:不只是深色模式

  • 分享至 

  • xImage
  •  

這個新章節要介紹主題樣式,但我一邊查資料一邊寫,卻越寫越不對勁——寫的方向跟實作內容對不上,所以想先釐清這章要談什麼。

一般談到主題樣式,多半是指深色/淺色模式,但我想分享的比較偏向遊戲的主題設定。切換主題時,會改變的內容包含:色系、圖片色系、角色服裝、裝飾圖案。不過我本身也有點好奇色彩模式是怎麼實作的,而且說實在,這才是 Web 開發比較常遇到的需求。😂

所以今天會先研究色彩模式的寫法,再參考 Bootstrap 的做法,回頭思考為什麼要用 SCSS。那麼我們開始吧!

需求分析

首先,來看看專案的主題樣式有哪些要注意的地方:

  • 使用者可以設定主題,網頁會在指定頁面或區塊套用樣式,並非全站套用。
  • 目前有四種主題,但主題屬於付費項目,未來不排除會再增加。
  • 設計稿上有每個主題的基礎色彩系統,但是部分設計元件的用色不在主題色系統中。並且依過往經驗,開發中有時會來回修改用色。
  • 重複出現的主題元件,例如按鈕。能分為能純用 CSS 畫出的簡單設計,以及需要用圖片呈現的複雜設計。

這樣看來,規劃主題樣式時,程式碼要保持可擴充性。並且顏色設定最好集中,方便管理。


研究顏色模式 CSS 寫法

有下面幾種做法,如果要讓使用者手動切換主題,還需要搭配 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 變數,彈性度高。

    • 能設定多組主題色系
    • 能指定套用的 HTML 區域
    • 能支援任何值(顏色、陰影、圖片…)
    :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);
    }
    

    CodePen 範例

💡 混用:利用 light-dark() 定義變數,例如 --bg: light-dark(#fff, #1a1a1a),同時保留 [data-theme] 用來手動切換。

可以看到,如果要做一般的顏色模式, CSS 變數的寫法最符合需求。它能設定複數色彩模式外,顏色設定還集中在主題區塊。


參考 Bootstrap

Bootstrap 的色彩模式是使用 data-bs-theme 屬性,在目標區塊的父層加上這個屬性,就能向下繼承色彩模式(放在 <html> 元素就是全站套用)。F12 開啟開發人員工具,我們可以看到色彩設定的方式其實與 [data-theme="..."] 相同。

bs主題色變數

不過,Bootstrap 還有一個我想要參考的點,那就是 Bootstrap 主題色設定的方法。在 Bootstrap 中為什麼可以只在 _variables.scss 新增一個顏色,就能產生出一組衍生樣式呢?

能簡單分成幾個步驟:

  1. 在 _variables.scss 新增一個基礎色的變數
    $milk-tea: #a0714f;
    
  2. 由 tint-color()、shade-color()、 shift-color() 等函式,換算出衍生色。
  3. 在 _variables.scss 的主題色 map 中,新增對應名稱與要套用的變數。
    $theme-colors: (
      "primary": $primary,
      "secondary": $secondary,
      // ...
      "milk-tea": $milk-tea,
    );
    
  4. 先用迴圈(SCSS 寫法)輸出 CSS 變數,然後讓元件的 .scss 讀取主題色 map,再跑一次迴圈產生對應的主題 class。

這個專案不需要像 Bootstrap 那樣,從一個顏色延伸出整套 UI 元件系統。
我預計用一組帶有 theme 前綴的 class,來套用色彩變數。但還是希望有個色彩 map 能讓開發者快速了解主題顏色設定,並且能用這個 map 產出主題 CSS 變數與通用主題樣式。


小結

回到開頭的問題:既然 CSS 變數已經能切換主題,為什麼還需要 SCSS?因為兩者負責的事情不同:

  • CSS 變數:在瀏覽器執行時切換主題。只要改變 data-theme,變數就會被覆寫。
  • SCSS:在編譯時產生程式碼。用 map 集中管理色票,再用迴圈輸出 CSS 變數與主題 class。之後新增主題,只要修改 map 就好。

至於圖片色系、角色服裝這類需要圖片的主題元件,會在後續章節另外介紹。


參考資料


今天比較像是行前說明,先了解要做什麼、怎麼做比較好後,再進入正題。

明天會介紹如何用 SCSS 管理色票!


上一篇
【Day 11】SVG 實作:路線圖(下) 把 path 當切糕,下刀兒!
下一篇
【Day 13】主題樣式:先利其器,認識 SCSS
系列文
從實務需求出發:前端視覺與 UI 互動開發實踐 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言