CSS 深色模式切換 (Dark Mode Toggle)

深色模式(Dark Mode / Night Mode)已成為現代網頁的標配。它不僅能減輕使用者在低光源環境下的眼睛負擔,也能讓網頁看起來更具現代感。

本篇將介紹如何使用 CSS 變數(CSS Variables)配合 prefers-color-scheme 或是自定義切換開關來實現深色模式。

使用 CSS 變數定義主題

這是實作深色模式最優雅的方式。我們先在 :root 定義一組顏色變數,然後在深色模式下覆蓋這些變數。

:root {
  /* 淺色模式(預設) */
  --bg-color: #ffffff;
  --text-color: #333333;
  --accent-color: #007bff;
}

[data-theme="dark"] {
  /* 深色模式 */
  --bg-color: #1a1a1a;
  --text-color: #f5f5f5;
  --accent-color: #375a7f;
}

body {
  background-color: var(--bg-color);
  color: var(--text-color);
  transition: background-color 0.3s, color 0.3s; /* 讓切換更平滑 */
}

自動偵測系統設定

透過 prefers-color-scheme 媒體查詢,網頁可以自動跟隨使用者的作業系統設定。

@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: #1a1a1a;
    --text-color: #f5f5f5;
  }
}

實作切換開關 (Toggle)

通常我們會提供一個切換按鈕,讓使用者可以手動選擇自己喜歡的主題。

HTML 結構

<button id="theme-toggle" class="theme-btn">切換深色/淺色模式</button>

實作預覽

主題展示區

這是一個模擬的主題切換區域。


### JavaScript 切換邏輯

只需切換 `<html>` 或 `<body>` 的 `data-theme` 屬性即可。

```javascript
const btn = document.querySelector('#theme-toggle');
const currentTheme = localStorage.getItem('theme'); // 讀取儲存的設定

// 初始化
if (currentTheme) {
  document.documentElement.setAttribute('data-theme', currentTheme);
}

// 點擊事件
btn.addEventListener('click', () => {
  let theme = document.documentElement.getAttribute('data-theme');
  if (theme === 'dark') {
    theme = 'light';
  } else {
    theme = 'dark';
  }
  document.documentElement.setAttribute('data-theme', theme);
  localStorage.setItem('theme', theme); // 儲存設定到 localstorage
});

CSS 對細節的處理

當切換到深色模式時,有些元素的樣式需要額外調整,以維持易讀性。

  1. 降低圖片亮度:全白的圖片在深色背景下可能過於刺眼。
    [data-theme="dark"] img {
      filter: brightness(.8) contrast(1.2);
    }
    
  2. 文字對比度:確保文字與背景之間有足夠的對比度(WCAG 標準建議至少 4.5:1)。
  3. 陰影調整:深色模式下的 box-shadow 應該要更深或改用發光效果(Glow),否則會看不清楚。
  4. 邊框顏色:原本淺灰色的邊框在深色模式下可能需要改為深灰色或透明。
建議將 data-theme 切換的 JavaScript 放在頁面最上方(<head> 內的 inline script),這樣可以防止頁面載入時產生「色彩跳動」(FouC - Flash of unstyled content)。