prefers-color-scheme 仅用于检测系统主题偏好,不可控制系统设置;需结合 css 媒体查询与 js 动态监听,注意覆盖优先级、首屏渲染时机及框架 ssr 限制,并通过 localstorage 持久化用户手动选择。

HTML暗黑模式不强制依赖系统主题,但可以主动读取并响应它——关键在 prefers-color-scheme 媒体查询是否被监听、是否被覆盖。
如何用 prefers-color-scheme 检测系统主题
浏览器通过 CSS 媒体查询暴露系统偏好,matchMedia 也能在 JS 中动态监听。它只读,不控制系统设置。
-
@media (prefers-color-scheme: dark)匹配系统设为深色时的样式,反之light匹配浅色 - 若用户未设置(如 Windows 10 旧版或某些 Linux 发行版),该媒体查询可能不触发,返回
no-preference - 不能靠它“开启”系统暗黑模式,只能适配——想强制切换必须用 JS + class 切换逻辑
- 示例:在
:root里定义变量,再用媒体查询覆盖::root { --bg: #fff; --text: #000; } @media (prefers-color-scheme: dark) { :root { --bg: #121212; --text: #e0e0e0; } }
为什么加了 prefers-color-scheme 却没生效
常见不是写错了,而是被更高优先级规则覆盖,或未考虑初始渲染时机。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
- CSS 文件加载顺序影响:后载入的样式会覆盖
@media规则,检查 DevTools 的“Computed”面板看哪条--bg被最终采用 - 内联样式(
style="background: white")或!important会直接压过媒体查询定义的变量 - JS 动态插入 class(如
document.body.classList.add('dark'))后,若未移除原有 class 或未同步更新变量,会造成冲突 - Next.js / Vue SFC 等框架中,CSS Scoped 或 SSR 渲染可能使媒体查询在服务端不生效,需用
useEffect或onMounted延迟到客户端执行
要不要把暗黑模式和系统主题强绑定
取决于产品定位。强绑定提升一致性,但牺牲用户自主权;解耦则需额外维护状态持久化逻辑。
- 强绑定适合工具类站点(如 VS Code 官网)、内部后台,减少认知负担
- 解耦更适合内容平台(如博客、文档站),用户可能白天用深色护眼、晚上用浅色防眩光
- 若解耦,必须用
localStorage记录用户选择,并在页面加载初期就应用对应 class,否则首屏闪白/闪黑 - 注意:iOS Safari 在“深色模式自动切换”开启时,
prefers-color-scheme会随日出日落变化,但不会触发 JS 的change事件——需轮询或监听window.matchMedia的addEventListener
真正难的不是监听系统主题,而是在用户手动切换模式后,还能平滑过渡、保留偏好、不破坏可访问性(比如不重置 prefers-reduced-motion 设置)。这些细节一旦漏掉,暗黑模式就只是个开关,不是体验闭环。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










