旋转动画必须起止值一致(如均为0deg)并显式设置animation: name duration linear infinite,否则易出现卡顿或非循环;需配合transform-origin:center确保绕中心旋转,且旧版浏览器需加-webkit-前缀。

用 @keyframes 定义旋转动画时,transform: rotate() 的起止值必须一致
很多人写 @keyframes spin 时习惯写成 from { transform: rotate(0deg); } to { transform: rotate(360deg); },这其实没问题,但容易忽略一个关键点:浏览器会把 360deg 当作独立状态,而非“回到起点”。如果动画时间短、帧率低,可能在循环衔接处出现微小卡顿或跳变。更稳妥的做法是统一用 0deg 起止,靠 animation-timing-function: linear 保证匀速:
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(0deg); }
}然后在 to 块里加一句 transform: rotate(360deg); 是多余的——浏览器不会因此多转一圈,反而可能干扰插值逻辑。
animation 属性必须显式设置 infinite 和 linear
只写 animation: spin 1s; 不会无限旋转,缺省的 animation-iteration-count 是 1,且缺省的 animation-timing-function 是 ease,会导致启动和结束有缓动,破坏旋转的连贯感。实际要用:
.loader {
animation: spin 0.8s linear infinite;
}注意三点:
-
0.8s比常见1s更符合人眼对“流畅加载”的感知阈值 -
linear必须显式声明,否则首尾减速会让旋转像“被拽住又松开” -
infinite不能省略,CSS 动画不会默认循环
元素本身要避免触发重排,优先用 transform 而非 width/height 动画
旋转动画如果套在带边框、内边距或内容流式布局的容器上,可能因尺寸变化引发 layout(重排),拖慢性能。正确做法是让旋转元素脱离文档流、尺寸固定,并用 transform-origin 控制中心点:
.loader {
width: 24px;
height: 24px;
border: 2px solid #eee;
border-top-color: #007bff;
border-radius: 50%;
animation: spin 0.8s linear infinite;
transform-origin: center;
}这里用 border + border-top-color 模拟环形进度,比用 SVG 或伪元素更轻量;transform-origin: center 确保绕自身中心转,否则可能偏移。
兼容性问题集中在旧版 Safari 和 IE,需加 -webkit- 前缀
iOS 9.3 及更早 Safari、IE 10–11 不识别无前缀的 @keyframes 和 animation。必须双写:
@-webkit-keyframes spin {
from { -webkit-transform: rotate(0deg); }
to { -webkit-transform: rotate(360deg); }
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.loader {
-webkit-animation: spin 0.8s linear infinite;
animation: spin 0.8s linear infinite;
}注意:现代项目若已放弃 IE 和旧 Safari,可去掉 -webkit-;但只要还支持 iOS 10 以下设备,就别省——不是所有用户都会升级系统。
真正难的不是写出旋转,而是让旋转在各种设备上都“不眨眼”。最常被忽略的是 timing-function 默认值和 transform-origin 缺失,这两点一错,动画就从“加载中”变成“卡住了”。



















