@keyframes 内不能使用 var(--x),因关键帧在解析时固化为静态值,var() 仅在样式应用时求值;正确做法是将变量定义在动画元素上,关键帧中用 calc(var(--x)) 引用并设 fallback。

不能在 @keyframes 块内部直接使用 var(--x) 改变或引用变量——浏览器会静默丢弃该声明,这不是 bug,是 CSS 动画规范明确禁止的行为。
为什么 @keyframes 里写 var(--x) 没反应
关键帧规则在 CSS 解析阶段就被固化为静态数值,不参与运行时计算。var() 只在“样式应用到元素”时求值,而 @keyframes 体(如 0% { opacity: var(--fade); })不属于该求值上下文。所有主流浏览器(Chrome、Firefox、Safari)均按规范处理:不报错,但整条声明无效。
常见错误现象:
-
opacity: var(--fade)写进@keyframes→ 元素始终不透明 -
transform: scale(var(--s))→ 动画卡在初始缩放值,无变化 - DevTools 的 computed 样式里看不到该属性,说明已被忽略
正确做法:变量挂元素上,关键帧用 calc(var(--x))
必须把变量定义在触发动画的元素(或其祖先)上,然后在关键帧中用 calc() 包裹引用。这是唯一被规范支持的路径。
@keyframes slide { 0% { transform: translateX(0); } 100% { transform: translateX(calc(var(--tx, 100px))); } }- 触发元素需带变量:
.box { --tx: 200px; animation: slide 0.4s; } - 务必提供 fallback:
var(--tx, 100px),否则未定义时calc()整体退为0 - 单位必须合法:写
calc(var(--tx) * 1px)可以,但calc(var(--tx) + 'px')是 JS 字符串拼接,在 CSS 里完全无效
JS 动态改值时要注意作用域和时机
用 element.style.setProperty('--tx', '250px') 触发重绘的前提是:该 element 正是动画所绑定的元素(或其父级),且变量名大小写、前缀 -- 完全匹配。
- 改全局主题?用
document.documentElement.style.setProperty() - 只改单个卡片?先
const card = document.querySelector('.card'),再card.style.setProperty() - 别用
document.body.style.setProperty():body 不是继承根,尤其在 Shadow DOM 下大概率失效 - 高频修改(如拖拽中实时更新
--x)必须套requestAnimationFrame,否则样式刷新撕裂或卡顿
容易被忽略的兼容性细节
即使语法正确,不同环境仍有坑:
- Safari 15.4 之前不支持
cubic-bezier(var(--a), ...)这类函数参数内嵌变量,只能用于calc()中的属性值 -
animation-duration: var(--dur)可直接生效,无需@keyframes配合,但animation-name: var(--anim)无效——动画名不能动态化 - 变量若被子元素内联样式覆盖(如
style="--tx: 50px"),则上级:root设置会被忽略,调试时得看 computed 样式链
真正难的不是写对语法,而是想清楚变量该挂在哪一层、fallback 是否兜底、以及 JS 修改后是否真被目标元素继承——这些地方一漏,动画就“不动”,而且毫无提示。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











