prefers-color-scheme 是 css 媒体查询特性,需写为 @media (prefers-color-scheme: dark) 等完整语法,配合 css 变量和 localstorage 可实现系统级深色模式响应与用户手动覆盖。

如何用 prefers-color-scheme 检测系统深色模式
浏览器原生支持,无需 JavaScript 就能响应系统主题变化。prefers-color-scheme 是一个媒体查询特性,值为 light 或 dark(极少数系统可能返回 no-preference)。
常见错误是直接写 @media (prefers-color-scheme) —— 这语法不合法,必须指定值:
@media (prefers-color-scheme: dark) {
body { background: #121212; color: #e0e0e0; }
}
@media (prefers-color-scheme: light) {
body { background: #ffffff; color: #333333; }
}
- 必须写成
(prefers-color-scheme: dark),不能省略冒号和值 - 多个媒体查询可叠加,比如同时判断
prefers-reduced-motion - 在 CSS 中声明顺序会影响层叠优先级,建议把
dark规则放在light后面,或用!important显式覆盖(不推荐)
为什么 CSS 切换有时不生效或延迟
根本原因通常是「CSS 加载时机」或「样式被更高优先级规则覆盖」。例如:页面已渲染完毕、JS 动态插入的样式表未触发媒体查询重计算;或者内联样式、!important、ID 选择器强行锁定了颜色。
- 确保 CSS 文件在
中通过<link>引入,而非动态document.createElement('link') - 避免用 JS 直接设置
element.style.backgroundColor,它会覆盖媒体查询结果 - Safari 14+ 和 Chrome 85+ 支持良好,但旧版 Safari(iOS 13.3 之前)对
prefers-color-scheme的初始值判断有 bug,可能首次加载时取错值 - 开发时可在 Chrome DevTools → Rendering → Emulate CSS media feature →
prefers-color-scheme手动切换测试
如何让自定义组件也响应深色模式(比如按钮、卡片)
关键不是给每个组件单独写两套规则,而是利用 CSS 自定义属性(CSS 变量)做主题抽象,再用媒体查询统一赋值。
:root {
--bg-primary: #ffffff;
--text-primary: #333333;
--border-normal: #e0e0e0;
}
@media (prefers-color-scheme: dark) {
:root {
--bg-primary: #121212;
--text-primary: #e0e0e0;
--border-normal: #333333;
}
}
.card {
background-color: var(--bg-primary);
color: var(--text-primary);
border: 1px solid var(--border-normal);
}
- 所有组件用
var(--xxx)引用变量,而不是硬编码颜色值 - 变量定义放在
:root,确保全局可访问;媒体查询里只负责“重设”,不重复声明组件样式 - 如果组件本身带内联 style(如 React 的
style={{ backgroundColor: 'white' }}),需改用 className + CSS 变量,否则无法响应
要不要 fallback 到 localStorage 记住用户手动切换?
要,而且必须加。因为 prefers-color-scheme 只反映系统设置,用户可能明确点过「切换到深色」但系统仍是浅色(比如 macOS 关闭了自动切换),此时应以用户操作为准。
- 监听用户点击按钮后,存
localStorage.setItem('theme', 'dark'),并手动加 class(如html[data-theme="dark"]) - 页面初始化时先读 localStorage,再查
prefers-color-scheme,前者优先级高于后者 - 不要只依赖 JS 切换 class——仍需保留
@media (prefers-color-scheme: dark),否则无 JS 时完全失效 - 注意:服务端渲染(SSR)场景下,首次 HTML 必须包含正确主题 class,否则会闪屏
真正麻烦的是「系统自动切换 + 用户手动覆盖」共存时的状态同步,比如用户切到深色,几小时后系统因日落到自动切回浅色——这时该听谁的?逻辑得写清楚,别让 localStorage 和媒体查询互相打架。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











