必须用@keyframes显式定义from{rotate(0deg)}to{rotate(360deg)},配合animation属性及transform-origin:center实现绕中心匀速无限旋转,仅写transform:rotate(360deg)或漏定义@keyframes均无效。

用 @keyframes 定义旋转动画,别漏掉 transform-origin
无限旋转的核心是 CSS 动画循环,不是靠 JS 控制。必须用 @keyframes 显式定义从 0deg 到 360deg 的 rotate() 变化,否则浏览器不知道转什么、怎么转。
常见错误是直接对元素写 animation: spin 1s infinite,但忘了定义 @keyframes spin,结果动画完全不生效;另一个坑是没设 transform-origin,导致旋转中心偏移(比如默认按左上角转,看起来像“乱飞”)。
实操建议:
- 旋转元素推荐用
display: inline-block或display: block,避免inline元素因基线对齐导致跳动 - 统一设
transform-origin: center,确保绕自身中心转 - 动画时长建议用
0.8s ~ 1.2s,太慢显得卡顿,太快易眩晕
@keyframes spin {
to { transform: rotate(360deg); }
}
.loading {
width: 20px;
height: 20px;
border: 2px solid #eee;
border-top-color: #333;
border-radius: 50%;
animation: spin 1s linear infinite;
transform-origin: center;
}
用 border 画圆环比 background 更可控
多数人想用纯色块旋转,但 loading 图标本质是“有缺口的环”,用 border + border-top-color 单独设色,能自然形成旋转中的“扫光”效果,比用 background 做渐变或遮罩更轻量、兼容性更好。
如果硬要用 background(比如要渐变色环),得配合 background-clip: padding-box 和透明边框,容易在 Safari 旧版出错;而 border 方案在 IE10+ 都稳。
关键点:
- 必须设
border-radius: 50%,否则是方框加边框 - 四边
border宽度一致,只改其中一边颜色,才能看出旋转方向 - 避免用
box-shadow模拟环,它不随transform平滑插值,iOS 上易闪烁
用 animation-timing-function: linear 保证匀速,别信默认值
CSS 动画默认是 ease(先快后慢),用在 loading 上会明显感到“一顿一顿”——开头加速、结尾减速,破坏等待预期。loading 要的是稳定节奏感,必须显式写 linear。
另一个隐藏问题:如果父容器有 will-change: transform 或 backface-visibility: hidden,某些安卓 WebView 会把 ease 错解析成卡顿,加了 linear 就立刻顺滑。
顺带一提:animation-direction: normal 可省略,但 animation-iteration-count: infinite 不能简写成 infinite 单独出现,必须和 animation 复合属性一起用,否则部分旧浏览器忽略。
适配暗色模式时,别只改颜色,检查对比度是否达标
很多人加了 @media (prefers-color-scheme: dark) 后只调 border-color,但忽略了 loading 图标需要至少 3:1 的对比度(WCAG AA 标准)。比如深灰背景上用浅灰环,肉眼几乎看不见。
实操建议:
- 用
hsl()写颜色,方便统一调整亮度,比如hsl(210, 10%, 70%)→hsl(210, 10%, 30%) - 测试时关掉浏览器缩放,用系统级“色彩滤镜”(如 Windows 高对比度模式)看是否消失
- 如果图标太小(box-shadow 扩展视觉尺寸,但别影响
transform-origin计算
最麻烦的其实是 SVG 方案——看似灵活,但 <animatetransform></animatetransform> 在部分邮件客户端完全不支持,纯 CSS border 环仍是上线首选。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











