根本原因是CSS变量在动画中静态求值:var()仅在动画初始化时解析为具体值,reverse仅倒序播放已计算的数值序列,不触发变量重解析,导致视觉跳变。

animation-direction: reverse 时 CSS 变量值突变的根本原因
不是变量“突变”,而是浏览器在倒播动画时,仍按原始 @keyframes 中的数值顺序取值,而变量本身未被重新计算——导致视觉上出现跳变。比如你定义了 --offset: 0px → --offset: 100px,加 reverse 后,它会从 100px 开始,但若关键帧里没写全中间状态,浏览器就用初始值“补空”,造成断层。
为什么 var() 在 animation-direction 下不重算
CSS 变量是静态计算的:在动画开始前,var(--offset) 就已被解析为具体数值(如 100px),后续 reverse 或 alternate 只改变播放顺序,不触发变量重解析。这和 JS 动态赋值完全不同。
-
@keyframes slide { 0% { transform: translateX(var(--offset)); } 100% { transform: translateX(calc(var(--offset) * 2)); } }—— 这里的两个var()都只在动画初始化时求值一次 - 加
animation-direction: reverse后,0% 状态(即translateX(100px))变成终点,但变量值不会自动变成calc(100px * 2),它只是把原序列倒着读 - 若你在 JS 中改了
document.documentElement.style.setProperty('--offset', '200px'),也不会实时反映到正在运行的动画中
如何让反转动画看起来平滑不跳
绕过变量在动画中的静态性限制,核心是把“可变逻辑”移到关键帧定义层,而非依赖运行时变量插值。
- 用预设多套
@keyframes,比如slide-in和slide-out,分别对应正向/反向逻辑,通过 class 切换控制 - 对需动态响应的场景,改用
transform+requestAnimationFrame手动控制,把var(--offset)提前读出并参与 JS 插值计算 - 如果必须用变量驱动,可借助
@property(需 Chrome 120+)声明受控类型:@property --offset { syntax: '<length>'; inherits: false; initial-value: 0px; },这样reverse时浏览器才真正按数值曲线插值
容易被忽略的关键点
真正卡住调试的,往往不是方向设错,而是你误以为 var() 是“活”的——它在动画上下文中本质是常量快照。哪怕你用 animation-timing-function: steps(1, end) 或 animation-iteration-count: infinite,变量值也只在第一帧解析一次。想让它动,得换机制,不是换写法。
立即学习“前端免费学习笔记(深入)”;


















