prefers-color-scheme 是静态媒体查询,仅首次加载时读取系统偏好,需配合 window.matchMedia 监听 change 事件并同步更新 data-theme 和 localStorage,且 CSS 变量须在 :root 定义默认值、data-theme 需在 DOMContentLoaded 前设置,才能实现无缝主题切换。

支持,但不是“自动同步”——prefers-color-scheme 只能读取系统当前偏好,不能监听运行时切换,更不能反向控制操作系统。手动切换按钮和系统偏好是两条独立路径,必须分别处理。
prefers-color-scheme 只在首次加载时生效
它是个静态媒体查询,页面加载那一刻取一次系统值,之后系统改了深色/浅色,网页不会自动响应。常见错误是只靠它初始化,却没加 window.matchMedia 监听器,导致用户切完系统主题后刷新页面才变。
- 必须用
window.matchMedia("(prefers-color-scheme: dark)")显式监听change事件 - 监听回调里要同时更新
document.documentElement.dataset.theme和localStorage - 不监听 = 用户系统切换后,页面主题“卡住”,体验断裂
data-theme 是你页面的唯一权威状态源
系统偏好只是默认值来源之一,用户手动点按钮后的选择必须覆盖它。用 data-theme 而不是 class 或 CSS 类名,是为了避免样式污染和语义模糊。
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 优先级顺序固定:localStorage > system preference > fallback(比如 light)
- 按钮点击时,不要只改 class,必须写
document.documentElement.setAttribute("data-theme", "dark") - 漏掉这步,CSS 中的
html[data-theme="dark"]选择器就失效
meta[name="color-scheme"] 不会随 JS 自动更新
这个 <meta name="color-scheme" content="light dark"> 是告诉浏览器“我支持两种模式”,但它本身不参与主题切换逻辑。很多人存了 localStorage 却忘了它,结果页面变暗了,但浏览器 UI(地址栏、滚动条)还是亮色。
立即学习“前端免费学习笔记(深入)”;
- 它只在页面初始渲染时起作用,JS 修改它无效
- 正确做法:在 HTML 模板里直接写死
content="light dark",别试图用 JS 动态改 - 真正影响浏览器 UI 的,是系统级设置 + 这个 meta 的声明组合,不是 JS 控制的
最容易被忽略的是:CSS 变量必须有默认值,且定义在 :root;data-theme 必须在 DOMContentLoaded 前设置好,否则首屏闪白/闪黑。这两处不出问题,系统适配和手动切换才能真正无缝。


















