CSS烟花效果需用@keyframes统一控制translate、scale、opacity,预设8方向动画类,absolute定位粒子于爆炸点,设forwards并animationend移除元素,配合will-change优化性能。

用 @keyframes 控制粒子位移与透明度变化
烟花效果本质是大量粒子从中心点向随机方向高速飞散,同时缩放变小、透明度归零。不能只靠一个 transform: scale(),必须把位移(translateX/Y)、缩放(scale)、透明度(opacity)全部塞进同一组 @keyframes,否则动画不同步,看起来像拖影或卡顿。
常见错误是给每个粒子单独写一套 @keyframes —— CSS 不支持动态生成关键帧,只能预设有限几套(比如 8 个方向),再用 JS 随机分配 class。
- 推荐写法:定义
@keyframes explode-0到@keyframes explode-7,每套对应一个角度区间(如 0°、45°、90°…),transform中用translate(200px, -200px)这类固定值模拟方向 - 所有动画时长统一设为
0.6s,animation-timing-function用cubic-bezier(0.2, 0.8, 0.3, 1)模拟初快后慢的物理衰减感 - 别用
ease-in-out:它中间匀速段太长,粒子会“飘”在半空
用 position: absolute + top/left 初始化粒子位置
粒子必须从同一个起点(烟花爆炸中心)出发,但 CSS 动画无法读取 JS 计算出的实时坐标,所以得靠定位把每个 容易踩的坑是直接用 烟花炸完粒子应该消失,而不是缩回原点。如果没设 必须加 单次烟花 100+ 粒子,每帧都要计算 transform 和 opacity,低端手机容易掉帧。不加优化的话,Chrome DevTools 的 Rendering 面板里能看到大量“Layout”和“Paint”条纹。 最麻烦的其实是颜色叠加和光晕——CSS 里没“发光”概念,top 和 left 设为爆炸点像素值(比如 top: 320px; left: 240px;)。transform: translate() 做初始偏移——这会导致动画起始位置不是你想要的“中心点”,而是元素默认文档流位置再平移,结果所有粒子从左上角炸开。
offsetParent 的坐标,再设置 element.style.top 和 element.style.left
position: relative,否则 absolute 粒子会相对于整个页面定位,一滚动就错位width: 4px; height: 4px;,太大显得像弹珠,太小(1px)在高 DPI 屏上糊成一片用
animation-fill-mode: forwards 防止粒子回退animation-fill-mode,动画一结束,transform 和 opacity 就恢复初始值,你会看到粒子“啪”一下闪回中心再消失,非常假。forwards,让动画最后一帧的样式(opacity: 0; transform: scale(0.1) translate(...))保持住。但注意:这会让 DOM 元素仍占位(虽然看不见),所以得配合 JS 清理。
animationend 事件里调用 element.remove(),别等 setTimeout —— 不同设备动画实际耗时可能有偏差display: none 替代 remove():它不释放 GPU 内存,粒子多的时候页面会越来越卡visibility: hidden + 重置 style 属性,比反复 new 更轻量用
will-change: transform, opacity 提升渲染性能will-change 是明确告诉浏览器“这个元素接下来要动”,让它提前把粒子图层提升到独立合成层。但别滥用——只在粒子即将播放动画前 1 帧加上,播完立刻移除,否则内存占用飙升。
element.style.willChange = 'transform, opacity',再触发 animation
animationend 回调里执行 element.style.willChange = 'auto'
will-change:它会把整个烟花区域都升层,得不偿失text-shadow 或 box-shadow 在粒子高速运动时会产生明显锯齿。真要接近真实烟花,得用 Canvas 或 WebGL,CSS 方案更适合做轻量提示性动效。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











