干净的脉冲缩放动画需用@keyframes定义scale(1)→scale(1.05–1.1)→scale(1)循环,配合ease-out、transform-origin:center及infinite;缺一不可。

用 @keyframes 实现干净的脉冲缩放动画
纯 CSS 脉冲动画不需要 JS,核心是定义一个从 1 倍缩放到略大于 1 倍、再回弹的循环。关键不是“放大”,而是「先快放、后慢收」的节奏感,否则会像卡顿的呼吸灯。
-
transform: scale(1)必须作为起始和结束状态,否则动画循环时会有跳变 - 推荐用
scale(1.05)~scale(1.1),超过scale(1.2)在小图标上容易显得突兀 - 动画时长控制在
0.3s–0.5s,配合ease-out或cubic-bezier(0.2, 0.8, 0.3, 1)更有“弹出感”
@keyframes pulse {
0% { transform: scale(1); }
50% { transform: scale(1.08); }
100% { transform: scale(1); }
}
给元素加脉冲动画时必须设 transform-origin
默认以元素左上角为缩放原点,按钮或图标会“往右下偏移”,看起来像在滑动而不是脉冲。不显式设置就会出视觉错位。
- 多数情况用
transform-origin: center;最安全 - 如果是贴左对齐的文本行内元素,可设
transform-origin: left center; - 绝对定位元素要结合
top/left和transform-origin一起看,否则动画中心会漂移
animation 属性漏写 infinite 就只播一次
脉冲动画本质是持续提示,但很多人复制代码时只写了 animation: pulse 0.4s;,结果 hover 后闪一下就停了——因为没声明循环次数。
- 完整写法必须包含
infinite:animation: pulse 0.4s ease-out infinite; - 如果只想 hover 时触发单次脉冲,改用
animation: pulse 0.4s ease-out 1;,且绑定在:hover上 - 注意:
animation-play-state: paused会冻结动画,调试时容易误以为没生效
移动端 Safari 上 transform 动画卡顿?加 will-change
iOS 15+ 之前,Safari 对未声明的 transform 动画常掉帧,尤其在列表项中批量使用时。这不是代码错,是渲染层没提前准备。
立即学习“前端免费学习笔记(深入)”;
- 在触发脉冲的元素上加
style="will-change: transform;"(或写进 class) - 不要滥用:仅对真正需要高频缩放的元素加,否则可能引发内存开销或重绘异常
- 如果已用
backface-visibility: hidden,它和will-change效果接近,二者选一即可
transform-origin 和 infinite 的组合缺失——动画看着“动了”,但位置偏、只动一次,用户第一反应是“CSS 没生效”,其实只是配置不全。



















