正确做法是仅用 opacity 动画配合独立 animation-delay 实现自然闪烁,禁用 transform/scale 避免重排、糊屏和布局干扰;js 预设 delay 数组并用 csstext 批量注入,结合 position: absolute + overflow: hidden + z-index 保障定位与层级。

只用 opacity + 独立 animation-delay 就能做出自然闪烁,加 transform 或 scale 反而破坏效果、触发重排、在高 DPI 屏上糊成一片。
为什么不能用 transform: scale(0) 模拟“消失”
视觉上像闪烁,但本质是错的:它不改变透明度,只是缩到看不见,元素仍占布局空间;动画过程中会意外触发浏览器重排(reflow),尤其在低端手机上卡顿明显;更关键的是,scale(0) 和真实 opacity: 0 无法叠加——比如你同时想加阴影或混合模式,效果就全乱了。正确路径只有一条:@keyframes 里只动 opacity,从 0.1 → 1 → 0.1,其他一概不动。
animation-delay 必须每个星星独立,且不能靠 CSS 里写 Math.random()
CSS 不支持运行时计算,animation-delay: calc(Math.random() * 3s) 是无效语法。必须由 JS 预生成或从固定数组取值:
- 推荐用预设数组,如
[0.3, 1.7, 2.4, -0.8, 1.1],避免每帧调Math.random()拖慢主线程 - 插入时直接设
star.style.cssText = "animation-delay: -${delay}s;",比链式赋值.style.animationDelay更快 - 负延迟(如
-1.2s)合法,表示动画已运行 1.2 秒后才开始渲染第一帧,能立刻进入中间状态,避免齐刷刷“一起闪”的假感
父容器和定位必须严格满足这三条
漏一条,星星就飘走、撑大页面、或随内容滚动:
-
body或包裹层必须设position: relative或position: fixed - 所有
.star元素必须是position: absolute,且top/left用 JS 随机生成(单位用px,别用%或rem) - 父容器必须加
overflow: hidden,否则星星溢出时会拉出横向滚动条
JS 批量生成别用 innerHTML +=,总数卡在 80–150 个
拼字符串再整段赋值 innerHTML,浏览器要反复解析 HTML、重建 DOM 树,100+ 星星在中低端安卓机上明显掉帧。正确做法:
- 用
document.createDocumentFragment()缓存所有.star节点,最后一次性append到容器 - 星星总数别超 150 —— 视觉上再多也看不出差别,但 GPU 渲染压力线性上升
- 尺寸统一用
width: 2px; height: 2px;,border-radius: 50%保圆,background: white即可,别加渐变或复杂阴影
最容易被忽略的是 z-index 和 overflow: hidden 的组合:没设 z-index,星星可能被内容遮住;漏了 overflow: hidden,页面宽度会被撑开——这两个问题在调试时往往不报错,但上线后用户第一眼就看到横向滚动条或星星不见了一半。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











