平滑 loading 动画的关键在于动得稳:需用 transform: translatez(0) 触发 gpu 加速、animation-fill-mode: both 保持首尾状态、linear 定速旋转,并配合 opacity/visibility 渐隐收尾。

直接用 @keyframes + animation 就能做出平滑 Loading 效果,但关键不在“能不能动”,而在“动得稳不稳”——多数卡顿、闪烁、跳帧问题,都出在动画触发时机和渲染层控制上。
为什么 loading 动画一上页面就卡或闪一下
浏览器在 DOM 构建完成前就开始解析 CSS,如果 .loading 元素初始状态没设好,或动画立即播放,就会和 layout/reflow 冲突。尤其当页面有大量图片、字体或 JS 同步执行时,animation 会被强制降帧甚至暂停。
- 常见错误现象:
opacity: 0的元素在animation-delay期间突然闪现、动画开始后第一帧明显偏移、移动端 Safari 上旋转抖动 - 根本原因:没切断动画与主线程布局的耦合;未启用硬件加速;未设置
animation-fill-mode - 必须加的防护项:
transform: translateZ(0)或will-change: transform触发 GPU 渲染层;animation-fill-mode: backwards确保延迟期保持初始态
animation 属性中哪些参数不能省
只写 animation: spin 1s infinite 是最简写法,但生产环境必须显式声明关键控制项,否则行为不可控。
-
animation-duration:必须明确数值,避免浏览器用默认值(部分旧版 Chrome 默认 0s) -
animation-timing-function:用linear而非ease控制旋转类 loading,否则转速不均;脉冲类可用cubic-bezier(0.3, 1.2, 0.7, 0.8)模拟弹性 -
animation-fill-mode: both:既保证延迟期维持from状态,又让结束帧(哪怕只播一次)停留住 -
animation-play-state: paused配合 JS 控制启停更安全,比靠 class 切换更稳定
旋转类 loading 最简可靠写法
不用 border 做环形 spinner,改用 transform: rotate() + border-radius 组合,兼容性更好、缩放不变形。
.loading-spinner {
width: 24px;
height: 24px;
border-radius: 50%;
border: 2px solid #e0e0e0;
border-top-color: #4285f4;
animation: spin 0.8s linear infinite;
animation-fill-mode: both;
transform: translateZ(0);
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
- 注意:不要只写
rotate(360deg),必须带单位;0deg和360deg在某些 Android WebView 中渲染结果不同 - 如果要适配深色模式,别用固定色值,改用
color-scheme: light dark+CSS custom property动态传色 - 移动端务必加
@media (prefers-reduced-motion: reduce)关闭动画,否则会触发系统级性能限制
加载完成时如何自然收尾
loading 不是播完就消失,而是要和后续内容“接上”。硬切 display: none 会导致重排,用 opacity + visibility 更稳妥。
- JS 控制时,别直接
el.remove(),先加 class:el.classList.add('loading-exit') - CSS 中定义退出动画:
.loading-exit { opacity: 0; visibility: hidden; transition: opacity 0.2s, visibility 0.2s; } - 监听
transitionend事件再移除元素,避免过渡未完成就被销毁 - 如果 loading 是覆盖全屏的遮罩,退出时记得恢复 body 的
overflow: hidden—— 这个细节 90% 的人会漏
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











