应使用抽象的@keyframes定义动画行为(如bounce-in),分离动画逻辑与触发逻辑,配合css自定义属性动态控制时长、延迟等参数,并注意forwards失效原因及js精准控制时机。

怎么用 CSS @keyframes 写出可复用的动画片段
直接写死在元素上的 animation 很难改,也不方便换效果。真正能当“生成器”用的,得从抽象动画行为开始——比如“弹跳”“淡入”“左右摇晃”,每个都定义成独立的 @keyframes 规则。
关键点在于:动画逻辑和触发逻辑要分开。动画本身不绑定具体元素、时长或延迟,只描述“从哪到哪”。例如:
@keyframes bounce-in {
0% { transform: scale(0.3); opacity: 0; }
60% { transform: scale(1.2); }
100% { transform: scale(1); opacity: 1; }
}
- 别在
@keyframes里写animation-duration或animation-timing-function——这些该由调用方控制 - 避免用
position: absolute或display等布局属性做动画,浏览器重排开销大,卡顿明显 - 想兼容老版本 Safari(iOS 9–12),记得加
-webkit-keyframes和-webkit-transform
怎么让一个 class 控制多种动画参数
纯靠写一堆 class(如 anim-bounce-300ms、anim-bounce-500ms)太傻。更实际的做法是用自定义属性(CSS Custom Properties)动态注入参数:
.anim-bounce {
--anim-duration: 0.4s;
--anim-delay: 0s;
animation: bounce-in var(--anim-duration) ease-out forwards;
animation-delay: var(--anim-delay);
}
- HTML 中直接改内联 style:
<div class="anim-bounce" style="--anim-duration: 0.6s; --anim-delay: 0.2s"> <li>JS 动态控制也方便:<code>el.style.setProperty('--anim-duration', '0.8s') - 注意:IE 不支持 CSS 变量,如果还要兼容 IE,得退回 BEM 命名 + 预处理器变量(如 Sass 的
$duration) - 动画没真正执行完——比如
animation-play-state: paused暂停后没恢复,或者 JS 中途调了el.style.animation = 'none' -
transform属性被其他样式覆盖(比如父级设置了transform: translateX(10px),子元素的动画transform就会被合并或丢弃) - 用了
opacity动画但元素本身有visibility: hidden,后者优先级更高,会强制隐藏 - 动画关键帧中漏写了终点状态(比如 100% 没设
opacity: 1),forwards只能保留最后一帧已声明的属性值 - 纯视觉反馈(如 hover 按钮缩放)→ 用
:hover+transition更轻量 - 需要精确控制播放次数、暂停/恢复、反向播放 → 必须用
el.getAnimations()和animation.play()/pause() - 想监听动画结束事件 → 用
animationend,但注意它不冒泡,且伪元素动画不会触发 - 频繁切换动画(比如轮播图每秒切一次)→ 避免反复 setStyle,改用
classList.toggle('anim-active')+ CSS 切换更稳
为什么加了 animation-fill-mode: forwards 还是回退
常见错觉是加了 forwards 就万事大吉,但实际失效往往因为:
JS 控制动画启停比纯 CSS 更灵活吗
是,但不是所有场景都需要 JS。判断依据很简单:是否依赖用户交互、数据状态或条件分支。
最易被忽略的是动画重叠问题:连续快速点击触发多次 animation,旧动画没结束,新动画又来,transform 堆叠错乱。解决方法是每次开始前先 el.getAnimations().forEach(a => a.cancel())。











