animation-delay 不能在 @keyframes 中使用 css 变量,因浏览器规范禁止在关键帧内读取自定义属性,否则整个 @keyframes 会被忽略;变量只能用于 animation-delay 等动画控制属性,需定义在 :root 或父容器中,并配合 calc() 在选择器中动态计算延迟值。

animation-delay 为什么不能直接用 CSS 变量写进 @keyframes
因为浏览器规范明确禁止在 @keyframes 块内读取自定义属性(CSS 变量),像 transform: translateX(calc(var(--dist) * 2)) 这种写法,整个 @keyframes 会被忽略——动画根本不会注册。这不是兼容性问题,是所有现代浏览器的统一行为。
所以别试图把延迟逻辑塞进关键帧里。真正能响应变量变化的只有 animation-duration 和 animation-delay 这类动画控制属性,它们在元素渲染时实时计算、重绘,但不触发重排。
- 变量必须定义在能被继承或作用域覆盖的位置,比如
:root或动画父容器上 - 推荐写带单位的值:
--anim-delay: 0.2s,而不是--anim-delay: 0.2,避免后续calc()里反复补单位 - 如果某个元素要“跳过延迟”,别设
--anim-delay: 0,直接用animation-delay: 0s覆盖,否则会受变量默认值干扰
如何用 CSS 变量批量控制一组加载项的递增延迟
用 :root 定义基准延迟,再配合 :nth-child() 或子选择器做偏移,是最轻量、无需 JS 的方案。
例如三个加载骨架:
:root {
--anim-delay: 0.15s;
}
.skeleton-item {
animation: pulse 1.2s ease-in-out infinite;
}
.skeleton-item:nth-child(1) { animation-delay: 0s; }
.skeleton-item:nth-child(2) { animation-delay: calc(var(--anim-delay) * 1); }
.skeleton-item:nth-child(3) { animation-delay: calc(var(--anim-delay) * 2); }
- 负延迟(如
calc(var(--anim-delay) * -1))会让动画从中间切入,视觉上容易跳帧,尤其在循环动画中行为难预测 - 更稳的做法是只用正向延迟 + 固定步长,比如
0s、0.15s、0.3s,节奏可控 - 如果用 JS 动态修改变量,记得触发一次重绘:比如读取
offsetHeight,否则部分浏览器可能不立即响应
animate.css 中 delay 类不生效?先检查 animate__animated
animate.css v4+ 强制要求:没有 animate__animated 类,任何动画都不会触发——哪怕你写了 animate__fadeIn 和 animate__delay-2s 也白搭。
正确结构必须是:
<div class="animate__animated animate__fadeIn animate__delay-2s">内容</div>
- 类名顺序无关,但
animate__animated缺一不可 - 自定义 delay 类(如
.animate__delay-var { animation-delay: var(--anim-delay, 0s); })若没加!important,可能被其他高优先级样式覆盖 - 检查 DevTools 中该元素的
animation-delay是否被父级的animation: none或内联style="animation-delay: 0s"覆盖
JS 修改 CSS 变量后动画没反应?不是变量失效,是没触发重绘
执行 el.style.setProperty('--anim-delay', '0.8s') 后动画没变,大概率是因为浏览器还没重新计算样式流。CSS 变量本身已更新,但动画系统没“感知”到上下文变化。
简单补救方式(选其一即可):
- 强制读取一个布局相关属性,比如
el.offsetHeight,触发同步重排重绘 - 给元素加个临时 class 再立刻移除(
el.classList.add('force-repaint'); el.classList.remove('force-repaint');) - 用
requestAnimationFrame包一层再改变量,确保在下一帧执行
另外注意:Safari 15.4+ 才稳定支持在 transition 中响应 CSS 变量变化;旧版 Safari 对 transform: translateX(var(--dist)) 这类用法会卡住不动——如果用的是 transition 替代 animation,这点必须验证。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











