环形进度条通过 SVG 的 stroke-dasharray 和 stroke-dashoffset 控制填充长度:前者设定虚线模式,后者偏移起点实现动态填充;用 CSS 自定义属性与 calc() 驱动动画,并配合 JS 更新居中文字,兼顾兼容性与响应式对齐。

用 stroke-dasharray 和 stroke-dashoffset 控制环形进度长度
环形进度条本质是 SVG 的 <circle> 或 <path> 元素,靠描边虚线(dash)模拟“填满”效果。关键不是靠 background 或 transform,而是用两个 stroke 属性动态控制可见段落:
-
stroke-dasharray设定虚线的“实段+空隙”长度组合,比如100,100表示画 100px 实线、留 100px 空隙;对整圆而言,通常设为circumference,circumference,让整个圆只有一段实线可被裁剪 -
stroke-dashoffset决定这根实线从哪开始显示,值越大,起点越往右偏移,看起来就像“未填充”部分变多 - 假设圆周长是
251.2(半径 40 的圆:2 × π × 40 ≈ 251.2),100% 进度时stroke-dashoffset应为0;0% 时应为251.2
用 CSS 自定义属性 + @keyframes 驱动动画
硬编码数值难维护,推荐用 CSS 自定义属性绑定进度值,并在动画中计算 offset:
:root {
--progress: 75;
--circumference: 251.2;
}
<p>.circle {
stroke-dasharray: var(--circumference);
stroke-dashoffset: calc(var(--circumference) - (var(--progress) / 100 * var(--circumference)));
animation: progress 1.5s ease-out forwards;
}</p><p>@keyframes progress {
from {
stroke-dashoffset: calc(var(--circumference) - (0 / 100 <em> var(--circumference)));
}
to {
stroke-dashoffset: calc(var(--circumference) - (var(--progress) / 100 </em> var(--circumference)));
}
}注意:stroke-dashoffset 是负向偏移才顺时针“增长”,但多数人更习惯写正数 offset 配合从大到小的动画 —— 所以上面用 calc() 把逻辑转成直观的“已填充比例”
百分比文字居中且随进度同步更新
纯 SVG 文字不会自动响应 CSS 自定义属性变化,得用 JS 或内联方式。最轻量做法是把 <text> 放进 SVG 内部,用 dominant-baseline 和 text-anchor 居中,并通过 JS 更新 textContent:
立即学习“前端免费学习笔记(深入)”;
- 别用绝对定位覆盖 SVG,容易错位或缩放失真
- SVG 宽高需固定(如
width="200" height="200"),<circle>的cx/cy和<text>的x/y都基于此坐标系 - JS 只需一行:
document.querySelector('text').textContent = `${progress}%`,配合动画触发时机调用即可
IE 不支持 calc() 在 stroke-dashoffset 中使用
如果必须兼容 IE11,不能依赖 CSS 计算,得用 JS 动态设置 style:
- 先用 JS 算出
offset = circumference * (1 - progress / 100) - 再赋值:
circle.style.strokeDashoffset = offset - 动画改用
requestAnimationFrame或 GSAP,避免 CSS 动画在 IE 中卡顿或不触发重绘 - 注意:IE 对
stroke-linecap: round渲染异常,建议统一用butt或在 SVG 外层加transform: rotate(-90deg)调整起始角度
真正麻烦的不是画圆,而是让数字和描边始终对齐、缩放时不失真、低性能设备不掉帧 —— 这些细节比动画本身更耗调试时间。


















