prefers-color-scheme 是 css 媒体特性,用于声明式适配系统深色模式,支持 chrome 76+、firefox 67+、safari 12.1+,值为 light/dark/no-preference;应结合 css 自定义属性与合理色彩体系实现语义化主题切换,而非简单反色或硬编码颜色。

如何用 prefers-color-scheme 检测系统深色模式
浏览器原生支持,不用 JS 就能响应系统偏好。关键不是“监听”,而是用媒体查询做声明式适配。
-
prefers-color-scheme是 CSS 媒体特性,只在支持的浏览器中生效(Chrome 76+、Firefox 67+、Safari 12.1+) - 值只有三个:
light、dark、no-preference(后者极少触发,可忽略) - 不能用 JS 直接读取“当前主题”,但可以用
window.matchMedia检查匹配状态,适合需要动态响应的场景 - 别写成
@media (prefers-color-scheme: dark) { body { background: black; } }就完事——深色模式不是简单反色,要重设整个色彩体系
为什么直接覆盖 background 和 color 很容易翻车
因为语义缺失。比如 color: #333 在浅色下是文字,到深色下可能变成背景上的灰斑;又比如按钮边框用 #ccc,深色里就看不见了。
- 优先用 CSS 自定义属性(
--text-primary、--bg-surface等),在媒体查询里批量切换值 - 避免硬编码颜色值,尤其别在深色块里继续用
rgba(0,0,0,0.1)这类“默认黑透明”——深色下它会变亮且突兀 - 图标、SVG 的 fill/stroke 也要随主题变,否则深色背景下白色 SVG 可能完全隐形
- 表单控件(
input、select)默认样式受系统影响大,建议显式重置 border/background/color
如何让暗色主题不“一黑到底”
真·深色模式不是把所有东西刷成 #000,而是保留层次、降低亮度对比、控制彩度。用户开深色模式,图的是省眼,不是进洞穴。
- 主背景别用纯黑,推荐
#121212(Material)、#1e1e1e(VS Code)或#1a1a1a—— 比#000更柔和,也方便做层级区分 - 表面层(卡片、弹窗)用稍亮一点的灰,比如
#2d2d2d,形成轻微明暗差,避免“贴片感” - 文字不要全用
#fff,正文用#e0e0e0或#d0d0d0,次要信息再降一级(#909090),保持可读性不刺眼 - 慎用高饱和色作强调色,深色下同样亮度的蓝/绿会更“跳”,建议降低一点饱和度或提高明度
兼容旧浏览器或 JS 禁用时怎么兜底
不能假设用户一定开着现代浏览器或允许 JS 执行。CSS 媒体查询本身无 JS 依赖,但 fallback 要靠结构设计。
立即学习“前端免费学习笔记(深入)”;
- 默认样式按浅色写(绝大多数用户仍用浅色),深色规则用
@media (prefers-color-scheme: dark)包裹,自然降级 - 别用 JS 动态加 class(如
document.documentElement.classList.add('dark'))作为唯一开关——JS 失败就彻底白屏或黑屏 - 如果必须用 JS 控制(比如同步 localStorage 主题设置),记得先用 CSS 媒体查询兜底,再用 JS 覆盖,而不是反过来
- 测试时关掉浏览器的深色模式,再手动改系统设置,确认页面没崩、文字没糊、交互控件没消失










