用ol+li搭建步骤条最语义化,data-status控制状态,css计数器生成序号,::after绘制连接线,属性选择器统一管理样式,响应式通过媒体查询调整布局与连线方向。

步骤条的HTML结构怎么搭才不容易翻车
用 ol(有序列表)是语义最合理的选择,每个步骤用 li,而不是一堆 div 堆砌。这样既利于屏幕阅读器识别,也方便后续用 CSS 计数器自动编号。
常见错误是把步骤状态(如“已完成”“当前”“未开始”)硬编码进文本里,导致后期改文案或加多语言时要反复改 HTML。正确做法是用 data-status 属性控制状态:
<ol class="step-bar"> <li data-status="done">填写信息</li> <li data-status="current">确认订单</li> <li data-status="pending">支付完成</li> </ol>
- 避免用 class 名如
step-done控制状态——CSS 类名应表达“是什么”,而非“是什么状态” -
data-status值统一用小写、短横线分隔(如is-current不推荐,current更直接) - 如果步骤数动态生成(比如从接口取),确保后端返回的 status 字符串与前端 CSS 选择器严格一致
用CSS计数器 + 伪元素画步骤线和数字
不用额外写数字标签,也不用 JS 插入序号。靠 counter-reset 和 ::before 就能自动生成带样式的圆圈数字。
关键点在于:步骤线不是单独画一条 hr 或 div,而是让每个 li 的右边框充当“连接线”,最后一个 li 去掉右边框即可:
.step-bar {
counter-reset: step;
display: flex;
list-style: none;
padding: 0;
margin: 0;
}
.step-bar li {
position: relative;
flex: 1;
text-align: center;
}
.step-bar li::before {
content: counter(step);
counter-increment: step;
width: 28px;
height: 28px;
line-height: 28px;
border-radius: 50%;
background: #e0e0e0;
color: #666;
font-size: 14px;
display: inline-block;
}
.step-bar li:not(:last-child)::after {
content: '';
position: absolute;
top: 14px;
right: -50%;
width: 100%;
height: 2px;
background: #e0e0e0;
}
- 注意
::after的定位依赖于li的position: relative,漏掉这句线就飘走 -
right: -50%是为了让连接线从当前项右侧出发,指向下一个项中心;若容器有 padding,需微调 - 别用
border-right代替::after——那样无法单独控制线长,且最后一个项要去掉边框时容易误删圆圈边框
如何用属性选择器切换步骤状态样式
状态样式全部通过 [data-status] 选择器控制,不新增 class,保持 HTML 干净。重点是颜色、背景、连接线三者的联动变化。
.step-bar li[data-status="done"]::before {
background: #4caf50;
color: white;
}
.step-bar li[data-status="done"]:not(:last-child)::after {
background: #4caf50;
}
.step-bar li[data-status="current"]::before {
background: #2196f3;
color: white;
transform: scale(1.15);
}
.step-bar li[data-status="pending"]::before {
background: #f5f5f5;
color: #999;
}
-
:not(:last-child)必须加在连接线规则里,否则“已完成”的最后一项也会把线染成绿色 - 别给
current状态加阴影或复杂动画——移动端点击反馈易失真,缩放(transform: scale)更稳 - 如果设计要求“当前项之后所有步骤灰掉”,不能只改
pending,还得加一条:.step-bar li[data-status="current"] ~ li::before来覆盖后续项
响应式断点怎么设才不破坏步骤逻辑
步骤条在小屏上堆成一列是常规解法,但很多人直接用 flex-direction: column,结果数字圆圈和文字错位、连接线方向混乱。
真正轻量的方案是:小屏下取消 flex 布局,让 li 自然块级排列,并用 margin-bottom 模拟间距,连接线改用 ::after 向下延伸:
@media (max-width: 768px) {
.step-bar {
flex-direction: column;
}
.step-bar li {
margin-bottom: 24px;
}
.step-bar li:not(:last-child)::after {
top: 28px;
right: 50%;
width: 2px;
height: 16px;
background: #e0e0e0;
}
.step-bar li[data-status="done"]:not(:last-child)::after,
.step-bar li[data-status="current"]:not(:last-child)::after {
background: #4caf50;
}
}
- 别用
height: 100%控制竖向连接线——父容器高度不确定,容易塌陷 - 竖向线的
right: 50%是为了对齐圆圈中心,配合transform: translateX(50%)更精准,但纯 CSS 实现可先省略 - 如果步骤超过 5 项,小屏建议改用垂直滚动容器(
max-height + overflow-y),而不是强行全显示
最常被忽略的是焦点管理:键盘 Tab 导航时,li 默认不可聚焦。如需支持无障碍,得加 tabindex="0" 并监听 keydown 处理空格/回车跳转——但这已超出纯 CSS 范畴,得留到 JS 阶段补全。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











