必须初始化变量、确保媒体查询顺序正确、为var()提供fallback并设置color-scheme属性,否则会导致白屏、闪动或控件颜色错乱。

直接用 @media (prefers-color-scheme: dark) 声明样式能响应系统偏好,但只靠它引入主题,90% 的页面会在深色系统下白屏、闪动或控件颜色错乱——根本不是浏览器不支持,而是变量没初始化、顺序写反了、var() 缺 fallback,也没告诉浏览器“我支持双主题”。
为什么写了 @media (prefers-color-scheme: dark) 却没反应
最常见的是把深色规则写在默认样式之前,或者只覆盖部分变量。CSS 不会补全你漏掉的值,它只会按声明顺序和作用域取值。
-
:root里必须先明确定义所有主题变量的浅色默认值,例如--color-bg: #ffffff;、--color-text: #333333; - 深色媒体查询块必须放在所有默认样式之后,否则会被后续无条件规则覆盖
- 不能只写
dark分支:系统设为no-preference或旧浏览器不识别时,未定义的变量会 fallback 到浏览器默认值(比如 Canvas 色可能意外变白) - 嵌套写法如
@media (max-width: 768px) { @media (prefers-color-scheme: dark) { ... } }在 Safari 12.1 之前完全失效
如何避免首屏闪动和变量失效
闪动本质是渲染时机错位:浏览器先按 :root 默认值画一遍,等媒体查询生效再重绘。iOS Safari 和 Android WebView 尤其明显。
- 在
里内联轻量 JS,用window.matchMedia('(prefers-color-scheme: dark)')立即检测,并给加data-theme="dark"类 - 所有关键样式同时写两套:
[data-theme="dark"] .card(防闪) +@media (prefers-color-scheme: dark) .card(保语义) - 每个
var()都加 fallback,例如background: var(--bg, #ffffff);,防止变量未定义时样式崩塌 - 别依赖服务端判断主题——SSR 无法读取客户端系统偏好,直出默认主题必然闪
怎么让表单、滚动条、SVG 也自动适配
CSS 变量只管你自己写的样式,原生控件(input、select、滚动条、svg fill)默认不读变量,得靠 color-scheme 告诉浏览器“我支持双主题”。
- 在
:root或html上加color-scheme: light dark;,Chrome 85+、Firefox 96+、Safari 15.4+ 会自动切换原生控件颜色 - 这个声明不影响自定义样式,只影响未被显式覆盖的系统级元素(比如未设
background的input) - 如果用了自定义滚动条(
::-webkit-scrollbar),就得手动在媒体查询里重写颜色
真正难的不是写对那几行 @media,而是确保每处 var() 都有 fallback、每个原生控件都被 color-scheme 覆盖、每次 DOM 渲染前 data-theme 已就位——这三个点漏一个,用户就可能看到半秒白屏或一个灰扑扑的输入框。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











