主题切换功能通过 localstorage 持久化保存用户选择,页面加载时读取并应用,交互时更新存储并实时切换样式;初始化需检查 localstorage、 fallback 到系统偏好、写入 data-theme 属性;切换操作须原子化执行,css 推荐用 data 属性驱动 + 自定义变量统一管理。

主题切换功能依赖 LocalStorage 持久化保存用户选择,页面加载时读取并应用,交互时更新存储并实时切换样式。关键在于避免闪烁、保证初始状态准确、兼容系统偏好与手动设置。
初始化时正确读取并应用主题
页面加载阶段需同步完成三件事:检查 LocalStorage 中是否已有用户选择;若无,则尝试读取系统偏好(prefers-color-scheme);最终将确定的主题写入 或 的 data-theme 属性,并触发对应 CSS 类生效。
- 使用
document.documentElement.setAttribute('data-theme', theme)统一控制根节点,CSS 中用[data-theme="dark"]等规则覆盖样式 - 避免在 DOM 尚未 ready 时操作,推荐放在
DOMContentLoaded回调或useEffect(() => {}, [])(React)中执行 - 不要仅靠 classList 切换——应先移除所有主题类,再添加当前主题类,防止残留冲突
切换操作需同步更新 UI 与存储
点击切换按钮时,逻辑必须原子化:获取下一主题 → 更新 LocalStorage → 修改 DOM 属性 → 触发 CSS 变更。中间任何一步失败都可能导致状态不一致。
- 推荐封装为函数,例如
setTheme('dark'),内部统一处理存储写入和 DOM 更新 - LocalStorage 写入后立即读取验证(
localStorage.getItem('theme')),便于调试或降级处理 - 可添加
transition: background-color 0.3s, color 0.3s等平滑过渡,但注意避免对data-theme属性本身做动画
响应系统偏好变化(可选增强)
监听 prefers-color-scheme 媒体查询变更,可在用户系统设置更改时自动同步主题(前提是用户未手动指定主题)。
- 用
window.matchMedia('(prefers-color-scheme: dark)')获取初始值,并调用addEventListener('change', ...)监听后续变化 - 仅当 LocalStorage 中无主题记录时才响应系统变更;一旦用户手动切换,就以 LocalStorage 为准,不再跟随系统
- 监听器需在组件卸载或页面离开前清理,防止内存泄漏
CSS 主题规则组织建议
主题样式应集中管理,避免重复定义。推荐采用 data 属性驱动 + CSS 自定义属性(CSS Variables)结合的方式。
- 在 :root 中定义基础变量,如
--bg-primary: #fff; --text-primary: #333; - 用
[data-theme="dark"] :root覆盖变量值,而非重写全部样式 - 关键颜色、背景、边框等通过变量控制,确保一处修改全局生效
- 避免在 JS 中硬编码颜色值,所有视觉表现交由 CSS 管理











