因为css变量本身不触发动画,必须在元素上显式声明transition并绑定到具体属性(如opacity、transform),且变量仅作为时长占位符;只改--duration值而未更新对应transition声明,浏览器不会重算动画逻辑。

为什么直接改 --duration 变量值动画却不生效
因为 CSS 变量本身不触发重绘,transition-duration 必须在元素上显式声明并解析为具体时间值,变量只是占位符。只改 :root 里的 --duration,但没更新对应元素的 transition 声明,浏览器根本不会重新计算过渡逻辑。
常见错误场景:
- 写了
:root { --duration: 0.2s; },但元素上还是transition: opacity 0.3s;—— 变量压根没被引用 - 局部覆盖了变量:
.btn { --duration: 0.18s; },却忘了在该元素上写transition: background-color var(--duration) ease; - 用了
all但没指定缓动函数,导致var(--duration)被忽略(transition简写中缺参数会整体失效)
transition 简写里怎么安全用变量
必须保证简写格式完整:属性名、时长、缓动函数三者缺一不可,且变量只能出现在时长位置。浏览器对缺失项极其严格——少一个参数,整条声明就静默丢弃。
正确写法示例:
button {
--transition-fast: 0.18s;
--easing: cubic-bezier(0.4, 0, 0.2, 1);
transition: background-color var(--transition-fast) var(--easing),
transform var(--transition-fast) var(--easing);
}
容易踩的坑:
- 写成
transition: background-color var(--transition-fast);—— 缺缓动函数,整条无效 - 逗号分隔时顺序错位:
transition: opacity var(--easing), transform var(--transition-fast);——opacity没有时长,transform没有缓动,全挂 - 混用单位:
--duration: 150ms;但简写里写成transition: all var(--duration) ease;—— 合法,但和0.15s语义等价;若变量值是"0.15"(缺单位),则完全失效
多个属性不同节奏时,变量怎么分档不乱套
别用 calc(var(--base) * 1.5) 动态算时长——CSS 变量不支持运行时运算,Safari 旧版甚至会直接忽略整条声明。更关键的是,语义模糊:你无法一眼看出 calc(var(--base) * 1.5) 对应的是按钮悬停还是模态框入场。
推荐做法是按交互语义预定义几档变量:
:root {
--transition-fast: 0.18s; /* 按钮、开关、图标 */
--transition-normal: 0.3s; /* 折叠面板、导航展开 */
--transition-slow: 0.45s; /* 模态框、全屏遮罩 */
--easing: cubic-bezier(0.4, 0, 0.2, 1);
}
<p>.modal {
--transition-slow: 0.5s; /<em> 局部覆盖,不影响全局 </em>/
transition: opacity var(--transition-slow) var(--easing),
transform var(--transition-slow) var(--easing);
}</p>
注意点:
- 每个逗号分隔项必须完整:属性、时长、缓动函数一一对应
- 避免用
all—— 会把box-shadow或border-color的微小变化也纳入过渡,引发意外重绘 - 模态框这类重量级动效,缓动函数建议用
cubic-bezier(0.25, 0.46, 0.45, 0.94),比默认ease更有缓冲感
JS 动态改变量后 transition 不触发怎么办
直接 JS 修改 element.style.setProperty('--duration', '0.25s') 通常无效,原因有两个:一是当前 transition 声明可能还没加载或已被覆盖;二是浏览器不会自动 re-evaluate 已存在的 transition 规则,除非属性值真正变化。
可靠做法:
- 确保变量已在 CSS 中被引用:
transition: opacity var(--duration) ease;存在且生效 - 触发重排:改完变量后,强制读取一个布局相关属性,如
getComputedStyle(element).opacity; - 更稳妥的方案是切换 class:
element.classList.add('fast-transition');,对应 CSS 中定义.fast-transition { --duration: 0.18s; } - 慎用
transition-delay配合 JS —— 它延迟的是「监听属性变化的起点」,不是播放起点;快速连续操作易丢帧
最常被忽略的一点:变量值变更后,必须依赖某个真实发生的属性变化(比如 opacity 从 1 → 0.8)才能触发动画,光改变量本身毫无作用。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











