可用CSS伪元素将<ol>视觉模拟为进度条:通过::before画圆点、::after画连接线,用class(如is-done/is-current)控制状态样式,保持HTML语义化与响应式适配。

ol 里用 CSS 伪元素模拟进度条效果
纯 HTML 的 <ol> 本身不带进度条,但可以用 ::before 和 ::after 在每个 <li> 上画出连接线 + 圆点,视觉上形成步骤条。关键不是“加进度条”,而是“让有序列表看起来像进度条”。
常见错误是直接给 <ol> 加背景色或 border —— 那会破坏语义,且无法精准控制每步状态(比如“已完成”“当前”“未开始”)。
- 把
<ol>设为position: relative,方便后续绝对定位连接线 - 每个
<li>设为position: relative,并用::before画圆点,::after画右侧横线(除最后一项) - 用
counter-reset/counter-increment控制序号,避免手动写 1. 2. 3. - 通过添加 class(如
is-done、is-current)切换圆点颜色和连线样式
怎么用 CSS 控制“当前步”和“已完成步”的样式差异
仅靠序号无法表达状态,必须靠 class。浏览器不会自动识别哪一步“已完成”,得由 JS 或服务端注入 class。
典型状态类名:is-done(已提交/完成)、is-current(高亮当前)、is-disabled(不可点击的后续步)。
立即学习“前端免费学习笔记(深入)”;
-
.step.is-done::before:设为实心绿色圆点,background: #4ade80 -
.step.is-current::before:设为蓝色边框+透明填充,border: 2px solid #3b82f6; background: transparent -
.step.is-done ~ .step::after:选中所有后续项的连线,设为虚线或灰色,表示“尚未激活” - 注意:不要用
:nth-child(n)硬编码状态,那会让样式和逻辑耦合,改步骤数就得改 CSS
为什么不用 JavaScript 动态生成 ol?
可以,但没必要。动态生成容易破坏可访问性(screen reader 可能读不出序号),也增加首屏 JS 依赖。
- 语义化优先:原生
<ol>天然表达“有序步骤”,AT(辅助技术)会正确朗读“第 1 项,共 4 项” - JS 只负责状态更新(比如表单提交后加
is-doneclass),不接管结构渲染 - 如果步骤数由 API 返回,用 JS 插入
<li>是合理的,但插入后仍应保持<ol>结构,而非换成<div>堆砌 - 避免在
componentDidMount或useEffect里反复重绘整个<ol>—— 改 class 就够了
移动端适配时最容易被忽略的细节
横屏连接线在小屏幕上会溢出或折行,圆点和文字对不齐是高频问题。
- 连接线不用固定宽度,改用
flex:给<ol>设display: flex; flex-direction: column,每个<li>内部用display: flex; align-items: center - 圆点用
flex-shrink: 0防止被压缩;文字区域用flex: 1自适应剩余空间 - 竖排时(如手机端),把连接线从“横向右”改成“纵向下”,只需改
::after的height和top,不用新增 DOM - 别忘了
@media (max-width: 480px)中重置font-size和padding,否则小屏上圆点和文字挤在一起
真正难的不是画出那根线,而是让状态变化、语义表达、响应式布局三者不互相打架。class 控制状态,CSS 控制呈现,HTML 控制结构 —— 拆开管,才不容易漏掉某一边。



















