必须同时满足三点:在:root中先定义浅色默认变量,添加<meta name="color-scheme" content="light dark">声明以启用原生控件适配,并将@media (prefers-color-scheme: dark)置于默认样式之后覆盖变量,缺一不可。

能用,但只写 @media (prefers-color-scheme: dark) 不够——漏掉默认值、没配 color-scheme、缺 <meta>,页面照样白底黑字或表单不响应。
为什么 @media (prefers-color-scheme: dark) 看似写了却没效果
这不是语法错误,而是常见结构性缺失:
- 只写了暗色规则,
:root里没设浅色默认值 → 浅色系统下变量未定义,var(--bg)回退到浏览器默认(常是白底黑字) - 没在
<head>加<meta name="color-scheme" content="light dark">→<input>、<select>、滚动条等原生控件卡在浅色外观,iOS Safari 尤其明显 -
color-scheme: light dark只写在 CSS 里(比如html { color-scheme: light dark; }),没配<meta>→ 大部分 WebView 和旧版 Safari 直接忽略 - 用
file://协议本地打开 HTML → Safari 禁用该媒体查询,Chrome 可能降级;必须用python3 -m http.server或本地服务测试
:root 变量 + 媒体查询的正确写法
核心是「先默认,再覆盖」,且变量名严格一致:
:root {
--bg: #ffffff;
--text: #333333;
--border: #e0e0e0;
}
@media (prefers-color-scheme: dark) {
:root {
--bg: #121212;
--text: #e0e0e0;
--border: #333333;
}
}
html {
color-scheme: light dark;
}
body {
background-color: var(--bg);
color: var(--text);
border: 1px solid var(--border);
}
- 深色规则必须放在默认值之后,否则层叠失效
- 别用
#121212这类硬编码色值,优先改用Canvas、CanvasText—— 它们随系统高对比度/深色设置自动微调 - 所有用到变量的地方(包括 SVG 的
fill、伪元素的background)都得靠var(--xxx),不能只在body里覆盖
如何让 <input>、滚动条等原生元素也变暗
仅靠媒体查询做不到。必须三者齐备:
立即学习“前端免费学习笔记(深入)”;
-
<meta name="color-scheme" content="light dark">放在<head>最顶部(静态写死,不能 JS 动态插入) -
html { color-scheme: light dark; }(CSS 层声明,配合 meta 起作用) - 滚动条需单独定义:例如
::-webkit-scrollbar-thumb { background: var(--border); },且该变量也得在@media (prefers-color-scheme: dark)里覆盖
漏掉 <meta>,哪怕媒体查询生效,<input> 底色仍是白的——这不是 bug,是浏览器 UA 渲染逻辑未被启用。
手动切换时怎么避免和系统检测冲突
prefers-color-scheme 是被动响应,用户点按钮后刷新就回退。要共存,就得用 data-theme 控制优先级:
- 初始化时读
localStorage.getItem('theme'),有值就用它;没值才 fallback 到window.matchMedia('(prefers-color-scheme: dark)').matches - CSS 里把
[data-theme="dark"]规则写在@media (prefers-color-scheme: dark)后面,确保手动切换更高优先级 - 监听系统变化时,只在用户没手动选过(即 localStorage 为空)时才更新
data-theme,否则会覆盖用户选择 - 切主题后必须同步
localStorage.setItem('theme', 'dark'),否则刷新即丢失
最容易被忽略的是:系统主题切换后,已打开的页面不会自动重绘 —— matchMedia 的 change 事件只在 Safari 14+、Chrome 87+ 稳定触发,旧版只能 reload 或轮询。


















