aria-current是唯一合法的状态标记方式,必须用aria-current="step"标识当前步、aria-current="true"标识已完成步,禁用class="active";图标用::before伪元素生成,连线用border+flex-grow实现,切换前须同步校验表单有效性。

aria-current 是唯一合法的状态标记方式
Bootstrap 官方没有 .steps、.step-bar 或任何内置分步组件,所有“状态变化”必须靠 HTML 属性驱动,而不是 class。用 class="active" 或 class="completed" 看似简单,但屏幕阅读器完全无法识别,也不支持 SSR/hydrate 同步——React/Vue 服务端渲染后容易错位,用户 tab 导航时焦点会跳过未激活项。
正确做法是:aria-current="step" 表示当前进行中(唯一被读屏软件识别的值),aria-current="true" 表示已完成(仅在需区分“完成”与“进行中”时使用),二者不能混用。服务端必须准确输出该属性,前端 JS 切换时也必须同步更新该属性,而非只改 class。
- 每步链接必须是
<a></a>,且href指向对应表单区域 ID(如#step-2),否则浏览器前进/后退和锚点跳转失效 - 禁用未激活项时,用
tabindex="-1"+pointer-events: none,别用disabled——后者直接砍掉键盘焦点 - 不要在 JS 中用
element.classList.add("active")控制状态,CSS 必须写成[aria-current="step"] { ... }
图标必须用 ::before 伪元素生成,且尺寸用 rem
硬插 <span>●</span> 或绝对定位图标,会在小屏文字折行后错位、重叠或悬空。所有状态图标(圆点、对勾、数字)必须统一由 ::before 生成,样式由 aria-current 属性控制。
关键 CSS 示例:
.nav-link::before {
content: "";
display: inline-block;
width: 1.25rem;
height: 1.25rem;
border-radius: 50%;
margin-right: 0.5rem;
vertical-align: middle;
}
[aria-current="step"]::before { background-color: #0d6efd; }
[aria-current="true"]::before { background-color: #198754; }
:not([aria-current])::before { background-color: #adb5bd; }
- 尺寸用
rem而非px,确保缩放和响应式下比例一致 - 必须加
vertical-align: middle,否则基线错位导致图标上浮或下沉 - 移动端字体建议降到
font-size: 0.875rem,避免nav-link高度撑开导致行距失衡
连线必须用 border-right + flex-grow,禁用 transform 和固定 width
所谓“进度延伸”,本质是连接线随步骤推进自动填满剩余空间。用 transform: scaleX() 或内联 style.width 会导致动画卡顿、缩放中心偏移、断点错位——尤其文字折行后,连线常拉长到容器外或断裂。
横排时标准写法:
.nav-item:not(:last-child) .nav-link {
border-right: 2px solid #e9ecef;
flex-grow: 1;
}
竖排时(@media (max-width: 576px))切换为:
.nav-link {
border-bottom: 2px solid #e9ecef;
margin-bottom: 1rem;
}
- 只对非末项画线,
:not(:last-child)是关键,否则底部多一条线 - 别用
gap-3这类工具类控制间距——flex column 下它们行为不稳定,必须在媒体查询里显式重置gap和padding - 绝对定位或
::after画线在小屏下极易偏移,尤其当步骤标题换行时
切换前必须校验,不能只改 UI
用户点“下一步”时,如果只更新 aria-current 和样式,会出现“UI 走到第 3 步,但第 2 步邮箱字段为空”的逻辑断裂。这会让后端收到不完整数据,或触发后续 JS 报错。
- 点击事件里必须调用
checkStepValidity(),而不是等最终submit时才校验 - 校验失败时,用
input.focus()定位到第一个无效字段,别只弹alert - “下一步”按钮要设
nextBtn.disabled = true直到当前步通过,别只加opacity: 0.5 - 含异步校验(如用户名可用性检查)时,按钮需进 loading 状态并设
disabled防重复提交
真正麻烦的不是画线或换图标,而是状态同步——aria-current、表单有效性、焦点位置、按钮禁用态,四者必须原子性更新,漏掉任一环,可访问性和业务逻辑就崩了。











