@media (prefers-color-scheme) 仅响应系统深色/浅色偏好,需配合 data-theme 类实现手动切换;默认设浅色样式,用媒体查询兜底深色,避免仅依赖其控制主题。

如何用 @media (prefers-color-scheme) 检测系统主题
浏览器原生支持通过 @media (prefers-color-scheme) 读取用户操作系统级的深色/浅色偏好,无需 JavaScript 就能响应式切换样式。它只匹配系统设置(macOS、Windows 10+、iOS/iPadOS、Android 10+),不跟踪页面手动切换状态。
常见错误是把它当成“页面主题开关”——实际它只是监听系统信号。如果你做了手动切换按钮,这个媒体查询不会随之改变,必须配合 CSS 自定义属性或 class 控制逻辑。
-
prefers-color-scheme: dark匹配系统设为深色模式时 -
prefers-color-scheme: light匹配系统设为浅色模式时(多数系统默认) -
prefers-color-scheme: no-preference极少见,仅当系统未声明偏好时触发
基础 CSS 写法:用 @media 覆盖默认颜色
推荐把浅色模式设为默认样式(更兼容老浏览器),再用媒体查询覆盖深色部分。这样即使不支持 prefers-color-scheme 的浏览器也能正常显示。
:root {
--bg: #fff;
--text: #333;
}
<p>@media (prefers-color-scheme: dark) {
:root {
--bg: #1e1e1e;
--text: #e6e6e6;
}
}</p><p>body {
background-color: var(--bg);
color: var(--text);
}</p>
注意:不要在 @media 块里重复定义整个样式表,只覆盖变量或关键属性。否则维护成本高,且容易漏掉 selector 优先级问题。
为什么不能只靠 @media 实现手动切换
因为 @media (prefers-color-scheme) 是只读的系统信号,你点按钮切到深色,系统偏好没变,媒体查询就不会重触发。
- 用户手动切换后,需给
或添加data-theme="dark"类 - CSS 规则要同时覆盖两种路径:
[data-theme="dark"]和@media (prefers-color-scheme: dark) - 否则会出现“系统浅色 + 页面深色”和“系统深色 + 页面浅色”的错乱组合
典型写法是把媒体查询作为兜底,data-theme 作为主控:
/* 默认浅色 */
:root { --bg: #fff; }
<p>/<em> 系统深色兜底 </em>/
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--bg: #1e1e1e;
}
}</p><p>/<em> 手动深色优先 </em>/
[data-theme="dark"] {
--bg: #1e1e1e;
}</p>
兼容性与调试要点
prefers-color-scheme 在 Chrome 76+、Firefox 67+、Safari 12.1+、Edge 79+ 支持良好,但 iOS Safari 12.2–13.1 有 bug:切换系统主题后不触发重绘,需刷新页面。
- 调试时用 Chrome DevTools → Rendering → “Emulate CSS media feature prefers-color-scheme” 模拟切换
- Safari 需在「开发 → 本地文件 → 勾选 prefers-color-scheme」才能在本地 HTML 文件中生效
- 避免在内联
style标签或 JS 中硬编码颜色值,否则无法被媒体查询接管
最易忽略的是:媒体查询本身不保存状态,也不触发事件。想同步 localStorage 或响应用户操作,必须用 JavaScript 监听 matchMedia 的 change 事件,而不是指望 CSS 自己“记住”切换过几次。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











