必须先在:root中显式定义浅色默认变量(如--bg: #fff),再用@media (prefers-color-scheme: dark)覆盖,否则深色模式下var() fallback导致样式崩塌;还需加color-scheme声明、避免闪屏、全面适配原生控件。

直接用 @media (prefers-color-scheme: dark) 配合 :root 中的 CSS 变量,就能实现自动跟随,但必须按固定顺序写,否则在 Safari 或旧版 Firefox 里会失效或闪屏。
为什么不能只写媒体查询不设默认值
浏览器解析 CSS 时,@media (prefers-color-scheme: dark) 的匹配结果还没确定,如果 :root 里没先定义浅色变量,深色模式下 var(--bg) 会 fallback 成 initial 或透明,导致白底黑字混搭、按钮消失等“样式崩塌”。
- 必须在
:root顶层先声明所有变量,默认值为浅色(如--bg: #fff) -
@media块只能用来覆盖这些已声明的变量,不能新建变量 - 变量名别带 dark/light 后缀(如
--bg-dark),否则无法被同一处var(--bg)复用 - 所有使用变量的地方都加 fallback:
background: var(--bg, #fff),防极端情况未定义
怎样避免首屏闪白或闪黑
闪屏不是 JS 慢,而是 CSS 渲染时机问题:页面先按默认主题渲染,等媒体查询生效后再重绘。iOS Safari 和部分 WebView 尤其明显。
- 在
标签上加color-scheme: light dark声明(用<meta name="color-scheme" content="light dark">)让浏览器提前知道支持双模式 - 确保
:root变量定义在 CSS 文件最前面,不要被@import或 JS 注入延迟 - 避免把变量定义在组件级选择器里(如
.card { --bg: #fff; }),媒体查询无法穿透覆盖 - 不用
transition包裹background或color,否则闪屏会变成“渐变闪”更刺眼
哪些元素容易被忽略导致夜间模式不完整
只改 body 背景和文字颜色远远不够。表单控件、SVG 图标、图片边框、Canvas 渲染区域默认不响应 prefers-color-scheme。
-
<input>、<textarea></textarea>、<select></select>等原生控件需显式设background和color,不能依赖系统默认 -
<img>在深色背景下若带白边,要加border: none或background: var(--bg) -
<svg></svg>内部文字或路径颜色需用fill: var(--text-color),不能写死#000 - 滚动条颜色需额外用
::-webkit-scrollbar+color-scheme双保险,Firefox 用scrollbar-color
真正难的不是写对两套颜色,而是在用户手动切换、系统偏好变更、页面刷新、SSR 渲染之间保持状态一致——prefers-color-scheme 是只读信号,一旦加了 data-theme 手动控制,就必须用 CSS 层叠顺序明确优先级,否则 Safari 会无视你的 JS 设置。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











