CSS变量无法被transition驱动,必须对具体属性(如background-color)设置过渡,且两端值需为可插值颜色;transition须写在默认状态中,配合:root与.dark类切换变量,并通过document.documentElement.classList.toggle('dark')触发重绘。

CSS 变量本身不能被 transition 驱动,所谓“平滑过渡”必须作用于具体属性(如 background-color),且两端值都得是可插值的颜色。
为什么 transition: --bg-color 0.3s 完全无效
CSS 规范不支持对自定义属性名做插值动画。浏览器会直接忽略这行声明,既不报错也不生效。你写的 transition: --bg-color 0.3s 等同于没写。
- 真正能过渡的只有原生属性:比如
background-color、color、border-color、opacity、transform - 变量只是“中间占位符”,最终渲染时被替换成具体值;过渡发生在这些具体值之间
- 如果一端是
transparent或inherit,插值可能中断或跳变
transition 必须写在默认状态(非 .dark)里
很多人只在 .dark 类里加 transition,结果切换时还是闪——因为默认态没声明过渡行为,浏览器从“无过渡”切到“有过渡”,第一帧就跳变。
- 正确写法:
body { background-color: #ffffff; color: #333333; transition: background-color 0.35s ease-in-out, color 0.35s ease-in-out; } -
.dark类里只负责提供目标值:background-color: #121212; color: #e0e0e0; - 所有参与过渡的属性,必须在默认态和
.dark态都写死具体颜色值,不能留空或用initial
:root 声明 + class 切换才是可靠链路
用 @media (prefers-color-scheme: dark) 只能响应系统设置,无法支持用户手动点击切换;而仅靠 JS style.setProperty() 动态改变量,容易覆盖整套主题声明,维护困难。
- 统一在
:root声明所有变量:--bg-primary: #ffffff;,再用:root.dark { --bg-primary: #121212; }覆盖 - 切换必须操作
document.documentElement.classList.toggle('dark'),不是body,也不是自定义data-theme属性(除非你额外写了对应选择器) - 初始化阶段必须读取
localStorage.getItem('theme')并立即设 class,否则首屏必闪
深色模式切换最容易被忽略的点
不是“怎么切”,而是“什么时候切”和“切完谁来重绘”。document.documentElement.classList.toggle('dark') 这一行执行后,浏览器会重新计算样式,但前提是:变量已定义、目标属性已声明、过渡已在基础规则中启用。漏掉任意一环,就只剩跳变。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











