旋转 Loading 动画应使用 @keyframes spin { to { transform: rotate(360deg); } },配合 will-change: transform 触发 GPU 加速,避免低端 Android WebView 卡顿;采用 border 圆环实现,兼容 iOS 8+/Android 4.4+,动画时长设为 0.8s 提升流畅感。

用 @keyframes 写旋转 Loading 动画,别直接套 PC 版
移动端旋转 Loading 不能照搬桌面端的 transform: rotate(360deg) 写法——很多低端 Android WebView(比如 UC、QQ 浏览器内核)对 transform 动画支持不稳,容易卡顿或跳帧。必须加 will-change: transform 或强制启用硬件加速。
推荐写法:
@keyframes spin {
to { transform: rotate(360deg); }
}
.loading-spinner {
width: 24px;
height: 24px;
border: 2px solid #eee;
border-top-color: #007aff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
will-change: transform; /* 关键:触发 GPU 加速 */
}-
border模拟环形,比 SVG 或伪元素更轻量、兼容性更好(iOS 8+、Android 4.4+ 都稳) - 动画时长设为
0.8s而非1s:人眼对 - 避免用
from { ... } to { ... }以外的中间帧——部分旧版 Safari 对多关键帧解析异常
在 iOS Safari 上旋转动画突然停顿?检查 transform-origin
iOS 12–14 的 WebKit 有个隐藏 bug:当元素没有显式设置 transform-origin,且父容器有 perspective 或 transform 时,@keyframes 旋转会中途卡住或重置角度。
解决方法很简单:
立即学习“前端免费学习笔记(深入)”;
.loading-spinner {
transform-origin: center; /* 必须显式声明 */
/* 其他样式... */
}- 不要依赖默认值,哪怕它看起来是
center - 如果 Loading 是绝对定位在按钮内的,还要确认父级没意外触发
transform: translateZ(0)—— 这类“优化”反而会干扰动画层
需要适配深色模式?别用 currentColor 做旋转条颜色
很多人图省事用 border-color: currentColor,指望跟随文本色自动变深/浅。但问题在于:currentColor 在动画中不会实时响应系统主题切换,除非手动触发重绘(比如 toggle class)。
更稳妥的做法是用 CSS 自定义属性 + 媒体查询:
:root {
--loading-color: #007aff;
}
@media (prefers-color-scheme: dark) {
:root {
--loading-color: #5ac8fa;
}
}
.loading-spinner {
border-top-color: var(--loading-color);
}- 不用 JS 监听
prefers-color-scheme变化,CSS 原生支持已覆盖 iOS 13+/Android 10+ - 避免把
--loading-color定义在.loading-spinner选择器里——那样无法被媒体查询覆盖
想让 Loading 更「轻」?删掉 animation-fill-mode
有些教程建议加 animation-fill-mode: forwards 让动画结束时保持最终状态,但 Loading 是无限循环,这个声明完全多余,还会在部分 Android 低版本上引发渲染异常(比如首帧延迟 100ms 才开始转)。
只要确保:
- 动画名、时长、迭代次数(
infinite)写全 - 不写
animation-fill-mode(默认就是none) - 不给元素设初始
transform,否则可能和 keyframes 冲突
移动端 Loading 的核心就两点:启动快、转得稳。所有炫技参数(如 cubic-bezier 缓动、多层叠加)在小尺寸屏幕上几乎不可感知,反而增加解析负担。


















