prefers-color-scheme 媒体查询必须写在 :root 之后,旧版 Safari 会忽略前置声明;变量须先在 :root 中声明默认值,媒体查询内仅可覆盖不可新增;手动切换需操作 document.documentElement 并用 html.dark :root 选择器;Bootstrap 5.3+ 需用 data-bs-theme="dark" 且加在 <html> 上;禁用 filter/invert 等伪暗色方案。

prefers-color-scheme 媒体查询必须写在 :root 之后
它不是开关,而是条件匹配器——浏览器只在系统设为暗色时才启用里面声明的样式。如果 @media (prefers-color-scheme: dark) 写在 :root 默认变量之前,旧版 Safari(12.1–13.x)会直接忽略整个块,导致暗色变量根本没加载。
常见错误是把暗色变量单独拎出来写成独立 CSS 文件再用 <link media="(prefers-color-scheme: dark)"> 引入——这不可靠:Chrome 会预加载但不应用,Firefox 可能延迟数秒才生效,且无法保证变量优先级。
- 所有变量必须先在
:root中声明默认值(哪怕只是--bg-color: #fff),否则var(--bg-color)在 no-preference 场景下 fallback 为transparent -
@media块里只能覆盖变量,不能新增;漏掉--border-color,用了border: 1px solid var(--border-color)的元素就会变透明 - 别嵌套:
@media (max-width: 768px) { @media (prefers-color-scheme: dark) { ... } }是无效语法,CSS 不支持媒体查询嵌套
手动切换时 class 必须作用于 html 元素
用户点击「深色模式」按钮后,JS 改 document.documentElement.classList.add('dark') 才有效。改 body 或某个容器的 class,:root 里的变量不会被重新计算——因为 :root 是 <html>,变量继承链断了。
典型现象:按钮点了,DOM 上确实多了 dark 类,但页面颜色没变。原因往往是 CSS 里写了 .dark :root { --bg-color: #121212; },而 JS 却加在了 <body> 上,选择器根本匹配不上。
立即学习“前端免费学习笔记(深入)”;
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
- 正确写法是
html.dark :root { --bg-color: #121212; },同时确保 JS 操作的是document.documentElement - 初始化要早于首屏渲染:在
<head>里内联一小段 JS 读取localStorage.theme并同步设置 class,否则首次加载必闪屏 - 不要用
style.setProperty()动态改变量——它会绕过媒体查询逻辑,让@media (prefers-color-scheme: dark)彻底失效
Bootstrap 5.3+ 必须用 data-bs-theme 属性
Bootstrap 自己的暗色模式不认 class,只响应 data-bs-theme="dark"。把它加在 <html> 上才全局生效;加在某个 <div class="card"> 上,就只影响那个卡片及其子组件。
常见错误是引入了 Bootstrap 5.2 或更早版本,却照着文档写 data-bs-theme——该属性从 v5.3.0 才开始支持,低版本会静默忽略,页面毫无变化。
- 检查 CSS 文件头部注释,确认版本号 ≥
v5.3.0 - 确保 CSS 包含完整的暗色变量定义;若用自定义构建,需显式启用
$enable-dark-mode: true - 局部启用时,目标容器必须是 Bootstrap 组件(如
card、navbar),普通<div>加了属性也无效
避免 filter/invert 这类“假暗色”方案
filter: invert(100%) 或 filter: brightness(0.7) 看似省事,实则破坏可访问性:文字对比度崩塌、SVG 图标翻转、阴影消失、渐变失真,且完全无法与 prefers-color-scheme 协同工作。
最典型的坑是给整页加 filter 后,发现表单控件(input、select)颜色异常,或滚动条还是亮色——因为原生控件不继承父级 filter,也不响应 CSS 变量。
- 真正适配原生控件,得加
html { color-scheme: light dark; },配合变量控制 - 图片处理要用
picture+source media="(prefers-color-scheme: dark)",而不是靠滤镜硬压 - border 和 shadow 发糊?不是颜色不对,是对比度不足——换用明确的中间灰(如
--color-border: #444),别直接套背景色变体
:root 里漏一个变量,或者 class 加错层级,整个暗色逻辑就断在第一步。

















