CSS变量不能直接在@keyframes中使用var(--x),因其静态定义与变量运行时求值生命周期不重叠;必须用calc(var(--x))且变量需定义在动画元素上,单位须严格匹配。

不能直接在 @keyframes 里写 var(--x),浏览器会静默丢弃整条声明——这不是兼容性问题,而是 CSS 规范明确禁止的行为。
为什么 var(--x) 在 @keyframes 中被忽略
因为 @keyframes 是静态规则定义,不参与运行时计算;而 CSS 变量的求值发生在元素渲染时。两者生命周期不重叠,所以 transform: translateX(var(--dist)); 这类写法会被直接跳过,动画可能完全不触发,或只执行剩余有效的关键帧。
所有现代浏览器(Chrome 110+、Firefox 115+、Safari 16.4+)都统一执行该限制,不是 bug,也无需 polyfill。
calc(var(--x)) 是唯一合法入口,但有硬约束
想让变量数值进入关键帧,必须包裹在 calc() 内,且仅限支持计算的属性(如 transform、top、background-position),不能用于 animation-name 或 opacity 等非计算型属性。
立即学习“前端免费学习笔记(深入)”;
-
calc(var(--offset))✅ 合法,括号不能省 -
calc var(--offset)❌ 语法错误 - 若
--offset定义为100(无单位),需写成calc(var(--offset) * 1px)才合法 - 若定义为
100px,就别再乘单位,否则单位重复报错 -
calc(var(--offset) * 2)在 Safari 15.4 之前不支持,需目标环境测试
变量必须定义在触发动画的元素上,而非仅 :root
即使你在 :root 里定义了 --offset: 200px,@keyframes 里用 calc(var(--offset)) 仍可能失效——变量必须落在该元素可继承或直接设置的作用域中。
- 网格项逐个右移?应写:
.grid-item:nth-child(1) { --offset: 100px; } - 不要依赖全局变量“自动生效”,要显式挂载到每个动画元素上
- 动画元素本身也要声明
animation,例如:.grid-item { animation: slideIn 0.5s ease; }
动画时长、延迟等参数必须绑定在元素上,不能塞进 @keyframes
animation-duration、animation-delay、animation-timing-function 这些属性支持直接使用 var(),且是唯一稳定路径:
- 写法必须拆开:
animation-duration: var(--dur, 0.4s);,不能放在animation简写里 - 务必带 fallback,默认值缺失会导致时长为
0s,动画不播 - 单位必须显式:用
400ms或0.4s都可以,但混用易引发维护混乱,建议统一用ms - JS 修改变量后,动画会实时响应,但不会触发重排,只重绘
真正容易被忽略的是作用域和单位——变量没定义在正确元素上,或单位漏写/重复,都会导致 calc(var(--x)) 失效,而浏览器不报错,只静默降级。动手前先确认这两点,比反复调 @keyframes 有效得多。


















