iT邦幫忙

2026 iThome 鐵人賽

DAY 29
0
Modern Web

從 UI/UX 設計到前端實作:30 天打造專屬的任務學習計時器系列 第 29 篇

DAY 29|使用者體驗優化(三):打造舒適的暗色模式(Dark Mode)體驗

  • 分享至 

  • xImage
  •  

對於需要長時間面對螢幕的開發者或工作者來說,亮白色的介面往往容易帶來視覺疲勞,因此不論是撰寫程式還是閱讀文獻, 「暗色模式(Dark Mode)」 早已成為許多人的預設首選。若使用者在專注工作的過程中切換到 TaskTimer,瞬間的高對比白光可能會讓人感到刺眼與不適。為了打造更貼心、減壓的專注環境,接下來我們要加上切換暗色模式的功能。


一、 暗色模式的核心設計思路

1. Bootstrap 5 原生主題屬性:直接透過在 <html> 標籤上切換 data-bs-theme="dark" 或 data-bs-theme="light",讓所有系統元件(Accordion、Modal、Card、Form Select)自動適應暗色視覺。

2. 主題開關(Toggle / Switch):在 Header 的多國語系選單旁,放置一個切換開關。

3. 自動偵測系統偏好:若使用者第一次開啟網頁,優先讀取作業系統/瀏覽器的預設主題(prefers-color-scheme: dark)。

4. 狀態持久化:將使用者手動選擇的主題儲存在 localStorage 中。


二、Header 切換開關 HTML

在 Header 的右上角工具列(語系切換選單旁邊)加入 Switch 開關:

<div class="form-check form-switch mb-0 d-flex align-items-center gap-2">
      <input 
        class="form-check-input mt-0" 
        type="checkbox" 
        role="switch" 
        id="darkModeToggle" 
        style="cursor: pointer;"
        onchange="toggleDarkMode(this.checked)"
      >
      <label class="form-check-label user-select-none mb-0" for="darkModeToggle" style="cursor: pointer;">
        <span id="themeIcon"></span>
      </label>
    </div>

暗色模式核心邏輯 (theme.js)

新增一個theme.js檔案,並在html中載入。

// 優先讀取偏好並套用至 <html>,防止畫面白光閃爍
const savedTheme = localStorage.getItem("app_theme");
const systemPrefersDark = window.matchMedia(
  "(prefers-color-scheme: dark)",
).matches;
let currentTheme = savedTheme || (systemPrefersDark ? "dark" : "light");

document.documentElement.setAttribute("data-bs-theme", currentTheme);

// 套用主題與同步 Switch 開關狀態
function applyTheme(theme) {
  currentTheme = theme;
  localStorage.setItem("app_theme", theme);
  document.documentElement.setAttribute("data-bs-theme", theme);

  // 同步 Switch 切換按鈕的勾選狀態 (暗色為 checked)
  const toggleInput = document.getElementById("darkModeToggle");
  if (toggleInput) {
    toggleInput.checked = theme === "dark";
  }
}

// 暴露全域切換函式給 HTML onchange 觸發
window.toggleDarkMode = function (isDark) {
  applyTheme(isDark ? "dark" : "light");
};

// DOM 載入後確認 Switch 按鈕開關位置正確
document.addEventListener("DOMContentLoaded", () => {
  applyTheme(currentTheme);
});

四、 補強微調:確保子任務 <select> 視覺質感

我們在之前開發時,子任務狀態使用的是自訂 <select>,在暗色模式下,只需要將 Background 顏色交給 Bootstrap 的主題變數,就能完美融入暗色背景:

// 在產生 statusBadgeHTML 時,加入 form-select 基礎 class:
const statusBadgeHTML = `
  <select 
    class="form-select form-select-sm border-0 ${subBadge.class} rounded-pill me-2 py-0 ps-2 pe-3 fw-bold" 
    style="width: auto; display: inline-block; cursor: pointer; font-size: 0.75rem; background-size: 8px 8px; background-position: right 0.4rem center;"
    onchange="changeSubtaskStatus('${task.id}', '${sub.id}', this.value)"
  >
    <option value="in_progress" ${subStatus === "in_progress" ? "selected" : ""}>
      ${langDict?.subtaskInProgress || '進行中'}
    </option>
    <option value="completed" ${subStatus === "completed" ? "selected" : ""}>
      ${langDict?.subtaskCompleted || '已完成'}
    </option>
  </select>
`;

暗色模式切換


小結

透過 Bootstrap 5 的 data-bs-theme,我們不需要額外撰寫數百行 CSS,就能讓全站組件(Modal、Accordion、Input、Dropdown)快速切換於明亮與暗色模式之間。


上一篇
DAY 28|使用者體驗優化(二):多國語系(i18n)切換與語系狀態持久化
下一篇
DAY 30|終點亦是起點: 完賽回顧、與新夥伴一起出發
系列文
從 UI/UX 設計到前端實作:30 天打造專屬的任務學習計時器 共 31 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言