应使用 nav+ol 构建语义化步骤条:ol 定义顺序,li 内 a 标签配合 aria-current="step" 标识当前步,确保可访问性与锚点跳转;图标用 ::before 伪元素生成,连线用 border-right(横排)或 border-bottom(竖排)实现,JS 同步需校验有效性并准确更新 aria-current。

用 nav+ol 搭语义结构,别碰 .progress
Bootstrap 5 根本没有原生步骤条组件,.progress 是数值型反馈控件,不是导航控件。硬套它会导致键盘不可访问、屏幕阅读器读不出“第几步”,且无法支持锚点跳转或条件跳步。必须用 nav 包裹有序列表:ol 表示步骤顺序,每个 li 里放 a,靠 aria-current="step" 标记当前项——这是唯一被读屏软件识别的方式。
常见错误是用 div 堆砌圆点+文字,或给 .progress-bar 加 width 模拟进度。这类写法在表单校验失败后状态不同步,DOM 和逻辑容易脱节。
图标全靠 ::before 生成,不插额外 DOM
所有步骤图标(数字、对勾、实心点)必须用 CSS 伪元素驱动,靠属性选择器切换内容:
- 当前步:
[aria-current="step"]::before { content: "●"; color: #0d6efd; } - 已完成步:
[aria-current="true"]::before { content: "✓"; color: #198754; }(注意:别混用"true"和"step") - 未开始步:
:not([aria-current])::before { content: counter(step); },配合counter-reset: step;自增编号
图标垂直居中要设 line-height 和 vertical-align: middle,否则基线错位;移动端建议字号降到 0.875rem,避免 nav-link 高度撑开导致行距异常。
立即学习“前端免费学习笔记(深入)”;
连线用 border-right+flex-grow,别用 transform 或绝对定位
横排时,给非末项的 .nav-link 加 border-right: 2px solid #e9ecef,再设 flex-grow: 1 让连线自动填满剩余空间;竖排(小屏)时移除 border-right,改用 border-bottom + margin-bottom: 1rem。
关键限制:.nav-item:not(:last-child) .nav-link 才画线,否则末尾多一条;用 gap 控制间距,别依赖 gap-3 这类工具类——flex column 下对齐不稳定;绝对定位或 ::after 画线在断点处极易错位,尤其文字折行后连线偏移。
JS 同步状态时,必须校验再更新 aria-current
点击“下一步”不能只改 UI 类名或 style.width,必须先调用 checkStepValidity() 校验当前字段。校验失败就 focus() 到第一个无效输入框,禁用按钮并阻止状态切换。
服务端渲染时,aria-current 必须由后端准确输出;否则 React/Vue hydrate 容易错位——比如后端标了 aria-current="step" 在第 2 步,前端 JS 却误判为第 1 步,状态立刻失同步。异步校验(如用户名可用性检查)期间,按钮要进 loading 状态且禁止重复点击。
最常被忽略的是:小屏竖排时,flex-direction: column 会改变 border-right 的生效逻辑,但很多人只改了布局没重置连线规则,导致竖排下连线消失或错位到顶部。


















