conic-gradient绘制环形进度条的核心原理是用角度顺时针辐射渐变画扇形,配合border-radius:50%、正方形尺寸、background-clip或遮罩实现环形轮廓;关键在0°起始、360°内按百分比动态计算终止角(如75%→270°),并用双色标叠加或透明裁剪控制显示区域。

conic-gradient 绘制环形进度条的核心原理
conic-gradient 是以元素中心为原点、按角度顺时针旋转的渐变。环形进度条本质就是用它画一个「从 0deg 开始、到 Ndeg 结束」的扇形色块,再配合 background-clip: text 或遮罩层露出环形轮廓。关键不是“画满圆”,而是控制渐变范围 + 配合透明背景或裁剪。
- 渐变起始角固定为
from 0deg,结束角由进度值决定:比如 75% 进度对应from 0deg to 270deg(360 × 0.75) - 必须设置元素为正方形(
width === height),否则环形会拉伸变形 - 默认渐变是实心扇形,要变成“环形”,得靠
background-color: transparent+ 边框或伪元素挖空中心
最简可行方案:用两个 conic-gradient 叠加实现环形
不用 SVG、不用 JS,纯 CSS 实现的关键在于:用一层渐变画进度,另一层渐变画“剩余部分”,两者拼成完整圆环,再通过透明度或颜色区分状态。
.progress-ring {
width: 120px;
height: 120px;
border-radius: 50%;
background: conic-gradient(#4a90e2 0deg, #4a90e2 270deg, #e0e0e0 270deg, #e0e0e0 360deg);
/* 270deg = 75% × 360deg */
}
- 第一个颜色段(
#4a90e2 0deg, #4a90e2 270deg)是已加载部分 - 第二个颜色段(
#e0e0e0 270deg, #e0e0e0 360deg)是未加载部分 - 两段必须首尾紧接,不能留空隙,否则会出现模糊过渡或白边
动态更新进度时,为什么直接改 background 不生效?
CSS 自定义属性(--progress)无法直接插入 conic-gradient 的角度计算中——浏览器不支持在渐变函数里做算术运算。
- 错误写法:
conic-gradient(... 0deg to calc(var(--progress) * 3.6deg) ...)→ 无效 - 正确做法:用 JS 动态设置内联样式,或借助 CSS Houdini(兼容性差,不推荐)
- 更稳妥的替代:用
@property声明类型化自定义属性(仅 Chromium 115+ 支持)
@property --progress {
syntax: '<number>';
inherits: false;
initial-value: 0;
}
.progress-ring {
background: conic-gradient(
#4a90e2 0deg,
#4a90e2 calc(var(--progress) * 3.6deg),
#e0e0e0 calc(var(--progress) * 3.6deg),
#e0e0e0 360deg
);
}
- 注意:必须声明
@property才能触发动画插值;否则角度不会平滑过渡 - Safari 和 Firefox 当前不支持该特性,生产环境仍建议 JS 控制
style.background
移动端和高缩放下环形边缘发虚怎么办?
conic-gradient 在非整数像素边界或 DPR > 1 设备上容易出现抗锯齿模糊,尤其环形内外边缘。
立即学习“前端免费学习笔记(深入)”;
- 强制开启硬件加速:
transform: translateZ(0)或will-change: background - 避免使用小尺寸(
),最小建议 <code>100px起 - 不要用
box-shadow模拟描边,改用outline或额外伪元素 - 如果必须适配超小尺寸,优先考虑 SVG
<circle></circle>+stroke-dasharray,渲染更稳定
实际项目里,conic-gradient 环形进度条的精度和动画表现,高度依赖运行时环境。别只测 Chrome Desktop。


















