最简圆形进度条方案是用conic-gradient配合CSS变量控制角度,关键需正确计算色标(360°×进度值)、用padding+background-clip实现空心环、设background-size:200%200%才能使background-position动画生效。

直接用 conic-gradient 做圆形进度条,现代浏览器下最简方案就是一行背景 + 一个 CSS 变量控制角度,无需 JS、不依赖伪元素遮罩也能跑通。但别急着抄代码——多数人卡在色标计算、圆环“空心”实现和动画卡顿这三处。
conic-gradient 的色标怎么算才对
关键不是写死角度,而是把百分比转成度数:360° × 进度值。比如 75% 就是 calc(360deg * 0.75) 或更稳妥的 calc(var(--progress) * 3.6deg)(因为 --progress: 75 是纯数字)。
常见错误是这样写:conic-gradient(#4caf50 0%, #4caf50 75%, #f0f0f0 75%)——这会画出 75% 的实色扇形 + 25% 的底色扇形,但边缘生硬、无过渡,且无法形成“环”视觉。
正确做法是只用两个色标,让第二色标从“进度结束点”开始透明或底色:
conic-gradient(#4caf50 0deg, #4caf50 calc(var(--progress) * 3.6deg), #f0f0f0 0)- 必须配
border-radius: 50%和固定宽高,否则不是正圆 - 如果要“缺口环”效果(如加载中旋转环),把第二色标设为 75%,第三色标从 75% 开始透明:
conic-gradient(#3b82f6 0%, #3b82f6 75%, transparent 75%, transparent 100%)
怎样让圆环真正“空心”,而不是实心饼图
仅靠 conic-gradient 只能画扇形,要变“环”,得配合视觉裁剪。最轻量做法是用 padding 缩小内容区,让背景只在 padding 区绘制:
- 给元素设
width: 100px; height: 100px; border-radius: 50% - 加
padding: 12px(即环厚),此时内容区只剩 76×76px - 背景用
background-clip: content-box,确保渐变只画在 padding 区 - 不加
background-clip时默认是border-box,渐变会铺满整个 100×100 区域,盖不住中心
另一种等效方式是用 ::before 伪元素盖住中心,但多一层 DOM,维护成本略高。
为什么 background-position 动画会不动或跳帧
想让环转起来,不能对元素本身加 rotate()(那会连文字一起转),得靠 background-position 拖动渐变起点。但它生效有硬性条件:
- 必须设
background-size: 200% 200%,否则background-position: 360px 0移动无效 - 动画关键帧里
from { background-position: 0 0; } to { background-position: 360px 0; }才能匀速转一圈 - Safari 15.x 和部分安卓 WebView 旧版不支持该组合,会静止或跳帧——别硬调,用
@supports not (background: conic-gradient())包裹降级方案 - 降级可用
border: 12px solid #f0f0f0; border-top-color: #4caf50; animation: spin 1s linear infinite;,兼容性拉满
动态更新进度时容易忽略的细节
用 JS 改 style.setProperty('--progress', 85) 是主流做法,但有两点常被跳过:
- 加
transition: background 0.3s ease让进度变化平滑,否则是瞬切 - 若进度从 0 → 100,
conic-gradient在 0% 时会退化成单色全圆,视觉上像“闪一下”,可加min-width: 1deg类似兜底逻辑(实际用max(1deg, calc(...))) - 无障碍需同步更新
aria-valuenow和aria-label,例如:el.setAttribute('aria-valuenow', '85')
真正难的不是写出来,而是让不同设备、不同进度值、不同语义需求下都稳得住——尤其是那个 background-size: 200% 200%,漏掉它,整个动画就废了。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











