旋转动画必须写全@keyframes的0%和100%(或from/to),命名禁用短横线,调用时需加引号;须设transform-origin: center、display:inline-block/block、宽高及animation: spin 0.8s linear infinite,优先用border圆环方案。

@keyframes spin 必须写全 0% 和 100%
只写 0% 没写 100%,或者用 from/to 却漏掉其中一个,动画会静默失败——浏览器不报错,但元素完全不动。名字也不能含短横线,比如 @keyframes loading-spin,调用时必须加引号:animation: 'loading-spin' 0.8s linear infinite。
常见错误还包括:只定义了 transform: rotate(360deg),却没写起始态 rotate(0deg);或把 @keyframes 放在 .loading 规则后面,导致 CSS 解析顺序出错,规则未生效。
旋转动画必须用 transform: rotate(),别碰 left/top/width
CSS 动画只有操作 transform 和 opacity 才能走合成层(compositor),触发 GPU 加速。一旦改 left、top、width 或 background-color,就会频繁触发重排(reflow)和重绘(repaint),动画立刻卡顿或跳帧。
-
border-top-color可以安全使用(它不触发布局) - 记得设
transform-origin: center,否则旋转中心可能偏移到左上角 - 对
<span></span>或<i></i>这类 inline 元素加动画前,先加display: inline-block或display: block,否则transform不生效
animation 属性要写全,尤其 infinite
只写 animation: spin 0.8s 是不够的——缺了迭代次数,默认只播一次。必须显式写 infinite 才能持续转圈。推荐写法是:animation: spin 0.8s linear infinite。
其他容易漏的关键点:
- 没给元素设明确宽高(比如空
<div>),旋转就看不见 <li>元素被设了 <code>display: none或visibility: hidden,动画不会启动 - 用 JS 动态加 class 时,如果同步执行(
el.classList.add('loading')),浏览器可能合并渲染,导致第一帧丢失;稳妥做法是加个setTimeout(() => el.classList.add('loading'), 0)
border 圆环旋转是最简可靠方案
比起伪元素、SVG 或多重 transform,用纯 border 实现旋转圆环最轻量、兼容性最好,且无需 JS 干预。核心就是利用 border 的颜色差异制造视觉动效:
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.loading {
display: inline-block;
width: 20px;
height: 20px;
border: 2px solid #eee;
border-top-color: #007bff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
}
这个方案在 Chrome 90+、Firefox 88+、Safari 14+ 上都能稳定运行。真正难的不是写出来,而是确保它在各种上下文里都“动得起来”:父容器是否 overflow: hidden?是否被 transform: scale(0) 临时隐藏过?这些细节比动画本身更容易让效果消失。











