纯 CSS 实现圆点进度条需用 transform: rotate() + absolute 定位手工排布环形点阵,border-radius 仅负责将单个点变圆,无法解决环形布局与顺序高亮问题。

纯 CSS 实现“圆点进度条”(即多个小圆点沿环形路径依次点亮)不能靠 border-radius 单独完成——它只负责把单个元素变圆,不解决“环形排列”和“顺序高亮”问题。真正可行的方案是用 conic-gradient + border-radius 做视觉基底,再配合伪元素或 JS 控制状态;若坚持纯 CSS,必须引入 transform: rotate() 和定位偏移来手工排点。
为什么 border-radius 本身做不了圆点进度条
border-radius: 50% 只能把一个块级元素变成圆形(比如 .dot { width: 12px; height: 12px; border-radius: 50%; }),但它完全不提供:环形布局能力、角度计算、顺序激活逻辑。试图仅靠它“摆一圈点”,结果只能是横排或竖排一堆圆点,离环形差得远。
常见错误现象:display: flex + flex-wrap: wrap 想“卷成圈”,实际只会折行;inline-block 加 text-align: center 也顶多居中一排,不是环。
- 环形排列必须依赖坐标系变换:每个点需独立
position: absolute+transform: rotate() translate() -
border-radius的唯一正向作用是确保单个点是正圆,且不被裁切(要求width === height,且父容器无overflow: hidden干扰) - 若点数固定(如 8 个),可用 CSS 变量 +
@property配合animation控制 opacity/transform,但兼容性限于 Chrome 110+ / Safari 16.4+
用 transform + 定位手排 8 个圆点的真实写法
这是目前最通用、无需 JS、兼容到 IE11 的做法。核心是:父容器设为相对定位,每个点绝对定位,用三角函数算出 xy 坐标(CSS 中用 calc() 近似)。
立即学习“前端免费学习笔记(深入)”;
假设环半径 50px,中心在 100px 100px,8 个点等分 360°(每 45° 一个):
.ring {
position: relative;
width: 200px;
height: 200px;
}
.dot {
position: absolute;
width: 12px;
height: 12px;
border-radius: 50%;
background: #3b82f6;
}
.dot:nth-child(1) { top: calc(100px - 50px); left: 100px; }
.dot:nth-child(2) { top: calc(100px - 35.36px); left: calc(100px + 35.36px); }
.dot:nth-child(3) { top: 100px; left: calc(100px + 50px); }
.dot:nth-child(4) { top: calc(100px + 35.36px); left: calc(100px + 35.36px); }
/* 后续类推,或直接用预处理器生成 */- 务必确认所有
.dot的width和height相等,否则border-radius: 50%会拉成椭圆 - 不要用
margin或padding调整位置——它们会破坏绝对定位的基准,改用top/left - 如果点要随进度“逐个点亮”,就给每个
.dot设不同animation-delay,例如animation: pulse 1s ease-in-out 0.2s forwards
用 conic-gradient 模拟“圆点进度”的取巧方案
如果你其实不需要真·离散圆点,只是想要“环形进度”的视觉感(比如加载中动画),conic-gradient 是更轻量的选择:它能画出扇形缺口,配合 border-radius: 50% 和 background-clip: content-box 就能做出空心环+渐变头的效果。
例如实现 60% 进度的环形条:
.progress-ring {
width: 100px;
height: 100px;
border-radius: 50%;
padding: 12px; /* 环厚度 */
background: conic-gradient(#3b82f6 0%, #3b82f6 60%, transparent 60%, transparent 100%);
background-clip: content-box;
}- 关键点:
background-clip: content-box确保渐变只画在 padding 区,形成“空心”效果;没这句就是实心饼图 -
conic-gradient的百分比是角度占比(60% = 216°),不是像素值,所以可直接绑定 CSS 变量:conic-gradient(#3b82f6 0%, #3b82f6 calc(var(--p, 0) * 1%), transparent 0%) - 此方案本质是“连续环”,不是“离散点”;若硬要模拟点阵,得叠加一层带透明间隙的
repeating-radial-gradient,但边缘锯齿明显,不推荐
容易被忽略的定位细节:transform-origin 和居中失效
很多人在用 transform: rotate() 排点时发现圆点绕左上角转、飘出可视区——根本原因是没设 transform-origin。
- 每个
.dot必须显式声明transform-origin: center,否则默认是0 0 - 如果用
inset: 0; margin: auto居中,注意它只在position: absolute且宽高固定时生效;若宽高由内容撑开,会失效 - 更稳妥的居中写法:
top: 50%; left: 50%; transform: translate(-50%, -50%),且确保父容器position: relative - 当点需要缩放或淡入时,
transform动画要和opacity分开写,避免触发重排;优先用will-change: transform, opacity提前告知浏览器
真正的难点不在“怎么让点变圆”,而在“怎么让它们乖乖站在环上并按序响应”。border-radius 只是最后一道整形工序,前面的定位、坐标、时机控制,才是躲不开的硬功夫。


















