应使用语义化 nav + aria-current="step" 构建步骤条,而非.progress;需同步校验、动态连线、无障碍聚焦及响应式适配,确保 DOM、逻辑与属性严格对齐。
别用.progress硬套步骤条,它不是导航控件
bootstrap 官方没有 steps 或 wizard 组件,.progress 是为数值型进度反馈设计的,只认 aria-valuenow,不表达“当前在哪一步”“哪些可点击”“哪些已校验通过”。强行改造成步骤条会导致:屏幕阅读器读“进度 60%”,而非“第二步”;键盘无法聚焦到各步骤项;动态跳过某步时 max/value 映射错乱;伪元素画的圆点与文字基线对不齐。
用 nav + aria-current 搭语义化结构
步骤条本质是导航控件,必须用语义化 HTML。推荐结构:
<nav aria-label="表单步骤">
<ol class="nav nav-pills">
<li class="nav-item">
<a href="#step-1" class="nav-link" aria-current="step">基本信息</a>
</li>
<li class="nav-item">
<a href="#step-2" class="nav-link">账户设置</a>
</li>
<li class="nav-item">
<a href="#step-3" class="nav-link">确认提交</a>
</li>
</ol>
</nav>
-
aria-current="step"是唯一合规标记方式,class="active"对读屏软件不可读 - 每步
href指向对应id区域,支持浏览器前进/后退和锚点跳转 - 禁用未激活项时,用
tabindex="-1"+pointer-events: none,别用disabled—— 后者会砍掉键盘焦点 - 服务端渲染需确保
aria-current由后端准确输出,否则 React/Vue hydrate 易错位
连线用 ::after + flex-grow 动态撑开
所谓“进度指示”,是指步骤节点之间的连接线随当前步推进而延伸。别用 transform: scaleX() 或直接写 style.width,容易卡顿或缩放中心偏移。
- 箭头用
border-right实现,配合flex-grow: 1在横排时自动撑开,断点切换更稳 - 只在非最后一项画箭头:
.nav-item:not(:last-child) .nav-link::after,避免底部多一条线 - 小屏竖排时重置
gap和padding:@media (max-width: 576px) { .step-nav { gap: 1rem; } .step-nav .nav-link { padding: 0.75rem 1rem; } } - 字体大小建议移动端降到
0.875rem,防止nav-link高度撑开导致行距失衡
每步切换前必须同步校验,不能只改 UI
用户点“下一步”不能只加 aria-current 或改样式,否则会出现“进度走到第 3 步,但第 2 步邮箱根本没填”的逻辑断裂。
- 点击事件里调用
checkStepValidity(),而不是等最终submit时才校验 - 校验失败时,用
focus()定位到第一个无效字段,别只弹alert - 禁用“下一步”按钮直到当前步通过:
nextBtn.disabled = true,别只加opacity: 0.5 - 若某步含异步校验(如用户名可用性),按钮要进 loading 状态,且禁止重复点击
- 进度连线宽度计算需基于当前步索引,不是百分比值 —— 第 2 步完成时,连线应覆盖前两个节点之间,不是简单设为
66%
aria-current、连线长度、键盘焦点链、甚至浏览器历史栈都要同步更新——漏掉任意一环,用户就会卡在“看起来能点,实际走不动”的状态里。


















