必须将变量全声明在:root中、@media(prefers-color-scheme:dark)写在默认样式后、设置color-scheme:light dark,否则深色模式失效;变量未声明或顺序错误会导致var回退unset,原生控件需显式重置样式且依赖js监听切换。

能直接用 CSS 实现,但必须满足三个硬性条件:变量全在 :root 声明、@media (prefers-color-scheme: dark) 规则写在默认样式之后、color-scheme: light dark 必须设置。
为什么写了 @media (prefers-color-scheme: dark) 却没反应
不是媒体查询失效,而是变量没定义或顺序错了。浏览器只认完整语法 @media (prefers-color-scheme: dark),漏掉冒号或值(比如写成 @media (prefers-color-scheme))就直接忽略整块规则。
- 浅色默认值根本没在
:root里声明 → 深色规则一覆盖,var(--bg-color)回退为unset,body 变透明、文字消失 -
:root中变量声明必须在所有@media规则之前;CSS 是顺序覆盖,不看“媒体查询优先级” - 别嵌套写:
@media (max-width: 768px) { @media (prefers-color-scheme: dark) { } }—— Safari 13.3 之前直接跳过
:root 里变量怎么声明才不翻车
变量不是全局常量,它的存在与否取决于声明位置和时机。:root 是唯一能保证全页面继承的位置;写在 .dark 或 body 里,<input>、<svg></svg>、伪元素就拿不到值。
- 所有主题变量(颜色、边框、阴影、字体大小)必须在顶层
:root块中一次性声明,默认用浅色值,例如--theme-bg-surface: #ffffff;、--theme-text-primary: #1a1a1a; - 变量名加语义前缀,比如
--theme-bg-surface,避免和第三方库(如 Tailwind 的--tw-)冲突 - 别依赖 fallback:
color: var(--text-primary, #333)看似安全,但拼错变量名(--text-prmiary)时直接回退到#333,深色背景下文字不可见
原生控件(<input>、滚动条、<svg></svg>)为啥还是亮色
CSS 变量对它们完全无效——它们不读自定义属性,也不响应 prefers-color-scheme。仅改 :root 变量,表单、滚动条、SVG 图标照样白底黑字。
- 必须在
html或:root上加color-scheme: light dark,否则 iOS Safari 和部分 WebView 强制渲染浅色表单 -
<input>、<select></select>、<textarea></textarea>要显式重置样式:background: var(--theme-bg-surface); color: var(--theme-text-primary); -
svg的fill和stroke必须用变量:fill: var(--theme-icon-primary);,不能靠继承或currentColor自动适配 -
::-webkit-scrollbar-thumb等伪元素也要用变量,且需单独写规则,不能指望它自动跟随主题
最易被忽略的点是:媒体查询只在页面加载时读取一次系统偏好,切换系统主题后已打开的页面不会自动重绘——除非刷新或手动触发。如果要做实时响应,得靠 JS 监听 matchMedia('(prefers-color-scheme: dark)').addEventListener('change', ...) 并同步更新状态。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











