缓冲动画在 Safari 上为啥不流畅?

IT人可馨 阅读 27

我最近在做一个加载状态的缓冲动画,用的是 CSS 动画配合 transform,Chrome 和 Firefox 都挺顺滑的,但在 Safari 上明显卡顿,甚至有时候直接不动了。是不是我哪里写得不对?

我试过加 will-change 和 translateZ(0) 但都没啥用。下面是动画的关键部分:

.spinner {
  width: 40px;
  height: 40px;
  border: 3px solid #f3f3f3;
  border-top: 3px solid #3498db;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
技术雨萱
Safari 的动画问题真是老生常谈了,你这代码本身没写错,但 Safari 对 border 动画的渲染确实有点拉胯。

问题出在 Safari 处理 border 旋转时的合成层策略上。你用 border 搭配 border-radius: 50% 画圆,再让整个元素旋转,Safari 会频繁触发重绘而不是走 GPU 合成,性能就崩了。

我来给你说下解决方案。

最稳妥的方案是改用 SVG 来做这个 spinner,SVG 动画在 Safari 上性能表现好很多,因为它天生就是矢量图形,渲染路径更优化。


class="path"
cx="25"
cy="25"
r="20"
fill="none"
stroke-width="3"
/>



.spinner {
width: 40px;
height: 40px;
animation: rotate 1s linear infinite;
}

.path {
stroke: #3498db;
stroke-linecap: round;
/* 这里用 stroke-dasharray 和 stroke-dashoffset 做圆环效果 */
stroke-dasharray: 90, 150;
stroke-dashoffset: 0;
animation: dash 1s ease-in-out infinite;
}

@keyframes rotate {
100% {
transform: rotate(360deg);
}
}

@keyframes dash {
0% {
stroke-dasharray: 1, 150;
stroke-dashoffset: 0;
}
50% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -35;
}
100% {
stroke-dasharray: 90, 150;
stroke-dashoffset: -124;
}
}


这个方案在 Safari 上跑得飞起,因为 SVG 的 stroke 动画走的是 GPU 加速路径,不会像 border 那样疯狂重绘。

如果你不想改 HTML 结构,只想用纯 CSS 撑着,还有个折中方案是用伪元素加 clip-path

.spinner {
width: 40px;
height: 40px;
position: relative;
animation: spin 1s linear infinite;
}

/* 用伪元素画半圆,两个拼成圆环 */
.spinner::before,
.spinner::after {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
border: 3px solid transparent;
box-sizing: border-box;
}

.spinner::before {
border-top-color: #3498db;
/* 强制提升合成层 */
transform: translateZ(0);
}

.spinner::after {
border-bottom-color: #f3f3f3;
transform: translateZ(0);
}

@keyframes spin {
100% {
transform: rotate(360deg);
}
}


这里需要注意,transform: translateZ(0) 要加在伪元素上而不是父元素上,因为真正在动的是这些伪元素的 border 渲染层。

不过说实话,SVG 方案还是更靠谱,我们项目里踩过这个坑,最后统一换成了 SVG spinner,Safari、iOS WebView 都没问题。纯 CSS 的 border 动画在 Safari 上就是个已知的性能黑洞,能躲就躲。
点赞 3
2026-02-28 14:11