css变量不能在@keyframes中直接使用,因规范禁止运行时求值;必须用calc(var(--x))包裹且变量定义在动画元素上,单位须严格匹配,否则被静默丢弃。

不支持。CSS变量(var(--x))不能在 @keyframes 块内直接使用,浏览器会静默丢弃整条声明——这不是兼容性问题,而是 CSS 规范明确禁止的行为。
为什么 var(--x) 在 @keyframes 中被忽略
因为 @keyframes 是静态规则,在样式表解析阶段就固化为数值;而 CSS 变量的求值发生在元素渲染时,两者生命周期不重叠。你写的 transform: translateX(var(--dist)); 不会报错,但会被当成无效声明跳过,动画可能卡在初始状态或只执行剩余有效帧。
所有主流浏览器(Chrome 110+、Firefox 115+、Safari 16.4+)统一执行该限制,无需 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 里写了 --tx: 200px,@keyframes 中的 calc(var(--tx)) 仍可能失效——变量必须落在该元素可继承或直接设置的作用域中。
例如网格项逐个右移:
@keyframes slideIn {
0% { transform: translateX(-20px); }
100% { transform: translateX(calc(var(--offset))); }
}
.grid-item:nth-child(1) { --offset: 100px; }
.grid-item:nth-child(2) { --offset: 180px; }
.grid-item { animation: slideIn 0.5s cubic-bezier(0.2, 0.8, 0.3, 1); }
注意:每个 .grid-item 都要显式设置变量,:root 的定义不会自动“透传”进关键帧上下文。
animation 属性本身可安全用变量,但需拆开写
animation 简写对变量极其敏感:任意子项未定义或类型错误,整条声明可能被丢弃。比如 animation: slide var(--dur) ease 中 --dur 为空,Chrome 会直接忽略整个 animation。
- ✅ 推荐拆开:
animation-name: slide;、animation-duration: var(--dur, 0.3s);、animation-timing-function: cubic-bezier(var(--x1, 0.25), var(--y1, 0.1), var(--x2, 0.25), var(--y2, 1)); - ✅ 所有
var()必须带默认值,否则未声明时animation-duration会退为0s,动画不播放 - ⚠️
animation-delay、animation-iteration-count虽支持变量,但 IE 完全不支持,需用@supports兜底
真正容易被忽略的是:开发者工具里看到“Computed”值正常,不代表关键帧生效了——那是元素样式层的计算结果,和 @keyframes 实际执行无关。验证是否起效,得看动画是否真的按变量值运动,而不是只看样式面板。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











