用 window.matchMedia 实现系统级主题自动切换,核心是监听 (prefers-color-scheme) 媒体查询变化事件,实时响应系统主题切换;通过 matches 属性读取当前偏好,结合 addEventListener 监听 change 事件,并在卸载时移除监听;CSS 用 @media + :root 变量实现样式解耦;手动设置(localStorage)优先级高于系统偏好。

用 window.matchMedia 实现系统级主题自动切换,核心是监听 (prefers-color-scheme) 媒体查询变化,而不是轮询或手动判断。它在用户系统主题切换瞬间触发事件,响应及时、零延迟。
检测当前系统主题模式
直接读取匹配状态即可获知当前偏好:
-
window.matchMedia('(prefers-color-scheme: dark)').matches返回 true 表示系统处于深色模式 -
window.matchMedia('(prefers-color-scheme: light)').matches返回 true 表示系统处于浅色模式 - 若两者都为 false(如旧浏览器不支持),可回退到默认浅色
监听系统主题实时变化
不能只查一次,必须绑定 change 事件才能响应后续切换:
- 调用
window.matchMedia('(prefers-color-scheme: dark)')获取 MediaQueryList 对象 - 用
.addEventListener('change', handler)注册监听器,e.matches即新状态 - 务必在组件卸载或页面离开前调用
.removeEventListener,避免内存泄漏
配合 CSS 变量实现样式自动更新
JS 负责“通知”,CSS 负责“呈现”。推荐用 :root 变量 + 媒体查询组合:
- 在
@media (prefers-color-scheme: light)中定义浅色系 CSS 变量 - 在
@media (prefers-color-scheme: dark)中覆盖同名变量为深色值 - 页面元素统一使用
var(--bg-color)等引用,无需 JS 操作 DOM 样式
兼容手动切换与系统偏好共存
用户可能想覆盖系统设置。此时需分层优先级:
- 优先读取 localStorage 中保存的手动选择(如
color_mode) - 若未手动设置,再 fallback 到
matchMedia获取的系统偏好 - 监听系统变化时,仅当用户未手动干预才同步更新页面主题











