conic-gradient默认起点为0deg(正右方向),非顶部,故需用from -90deg校正;变量须参与calc(var(--p)*3.6deg)角度计算,并配合background-clip: content-box和padding实现环形空心效果。

直接用 conic-gradient 配合 CSS 变量就能实现图形进度条,不需要 JS 每次重绘,也不依赖 SVG —— 但变量必须参与角度计算,且起始方向要对齐顶部,否则进度值会“偏移”。
为什么 conic-gradient 的 0% 默认不在顶部
conic-gradient 的默认起点是 0deg,对应正右方向(3 点钟位置),不是顶部(12 点钟)。这和多数 UI 场景的直觉相反,直接写 conic-gradient(red 0%, red 75%, #eee 75%) 会导致进度从右边开始“长出来”,像缺了一块。
- 必须显式加
from -90deg把起点拉到顶部:conic-gradient(from -90deg, #4a9eff 0%, #4a9eff calc(var(--p) * 3.6deg), #f0f0f0 0) - 别用
transform: rotate(-90deg)整体旋转容器——文字、伪元素、子内容全跟着转,指示器错位 - 如果要用 JS 动态设变量,记得带单位:
el.style.setProperty('--p', '65')(纯数字)或'65deg'(仅当变量用于角度偏移时)
怎样让变量真正控制“露出多少”而不是“画到哪”
单纯在色标里写 calc(var(--p) * 3.6deg) 只是画出一个扇形,它还是实心饼图。要变成环形进度条,得让中间“空出来”。
- 最轻量做法:用
padding缩小内容区 +background-clip: content-box,确保渐变只画在 padding 区域 - 示例结构:
width: 120px; height: 120px; border-radius: 50%; padding: 24px;→ 环厚 24px,中心留空 72×72px - 漏掉
background-clip: content-box是常见空白原因:默认border-box会让渐变铺满整个 120×120 区,盖住中心却没裁剪 - 别指望
transparent色标能“挖空”——它只是透明,底下若无背景就会透出父容器,不是真正的空心环
动画卡顿或不动?检查这三个硬性条件
想让进度变化带平滑过渡,不能只靠 transition: background 0.3s —— conic-gradient 本身不支持 transition,必须靠 background-position 驱动,而这有严格前提。
立即学习“前端免费学习笔记(深入)”;
- 必须设
background-size: 200% 200%,否则background-position移动无效 - 动画关键帧要写死像素值:
@keyframes spin { from { background-position: 0 0; } to { background-position: 360px 0; } } - Safari 15.4 以下、部分安卓 WebView 不支持该组合,会静止或跳帧——不是代码错,是引擎限制,降级方案得另配
@supports
移动端和小程序里变量还能用吗
变量本身可用,但 conic-gradient 在微信小程序中完全不识别,连语法解析都跳过。你在 H5 写的 style="--p: 80" 到小程序里会变成 background 值为空字符串,进度条直接消失。
- uni-app 或 Taro 项目必须做平台判断:
v-if="$platform === 'h5'"用conic-gradient,否则 fallback 到双半圆 +clip-path方案 - 别信“小程序基础库升级就支持了”——截至 2026 年 5 月,微信官方文档仍未列入
conic-gradient支持列表 - 变量名冲突风险:多个进度条共用
--p时,CSS 层叠会互相覆盖,建议按实例命名,如--progress-task1
最易被忽略的是:变量传入后,calc() 里单位缺失或类型错配(比如传字符串 "75%" 却没 strip 百分号),浏览器静默失败,进度条卡在 0 —— 这类问题不会报错,只能靠 DevTools 里实时看 computed style 中 background 值是否已展开为有效角度。

















