bootstrap 官方无内置步骤条组件,应使用语义化 nav+ol/ul 结构配合 aria-current="step" 实现;禁用 disabled 改用 tabindex="-1";响应式需分层控制布局与连线;进度指示须与表单校验强绑定。

Bootstrap 官方没有 .steps、.step-bar 或 .progress-steps 这类内置组件,所谓“Bootstrap 步骤条”基本是开发者自建结构+CSS,或第三方封装。用 .progress 强行改造成步骤条,语义错乱、无障碍失效、交互受限——这不是偷懒,是埋雷。
用 nav + aria-current 搭语义化步骤导航
步骤条本质是导航控件,不是数值反馈器。必须用语义化 HTML(如 <nav></nav> 包裹 <ol></ol> 或 <ul></ul>),每步用 <li class="nav-item"> + <a class="nav-link"></a>,靠 aria-current="step" 标记当前项。
-
aria-current="step"是唯一合规方式;class="active"对屏幕阅读器不可读,也不符合 Bootstrap 5+ 推荐实践 - 禁用未激活项时,别用
disabled——它会砍掉键盘焦点;该用tabindex="-1"+pointer-events: none - 每步
<a></a>的href应指向对应表单区域(如#step-2),支持浏览器前进/后退和锚点跳转 - 服务端渲染时,确保
aria-current属性由后端准确输出,否则 React/Vue hydrate 容易错位
响应式布局:横排 → 竖排不能只靠 flex-column
小屏下步骤文字折行、箭头拉长、间距爆炸,是硬套 flex-column 的典型副作用。真正可控的做法是分层控制:
- 大屏用
col-12 col-md-3配合d-flex横向均分;移动端加@media (max-width: 576px)单独重置 - 箭头不用伪元素硬写,改用
border-right+flex-grow: 1动态撑开,避免断点错位 - 只在非最后一项画箭头:
.nav-item:not(:last-child) .nav-link::after,否则底部多一条线 - 竖排时重设
gap和padding:gap: 1rem、padding: 0.75rem 1rem,别依赖gap-3这类响应式工具类——它们在 flex column 下对齐逻辑不稳定
别把 .progress 当步骤条用
<div class="progress"> 是为百分比型进度反馈设计的,<code>aria-valuenow 表示的是 0–100 数值,不是步骤编号。强行改造会出三个硬伤:
- 键盘用户无法感知“当前在第几步”,读屏软件只读“进度 60%”,不是“第二步”
- 每个步骤无法独立设置链接、焦点、点击区域,交互能力归零
- 步骤数动态变化(比如跳过第 3 步)时,
max/value很难映射准确,JS 同步成本高、易出错 -
.progress-bar默认是连续色块,硬塞圆点图标会破坏视觉节奏,且无法对齐文字基线
带进度指示的连线怎么画才稳
所谓“进度指示”,是指步骤节点之间的连接线随当前步推进而延伸。这条线不该用 JS 直接写 style.width,更不该用 transform: scaleX() 却不设 transform-origin。
- 推荐用伪元素
::before+width+ CSStransition,宽度用calc((100% - (N - 1) * gap) / N)动态算,避免硬编码 33.33% - 若某步异步校验(如用户名可用性检查),连线状态必须等校验完成再更新,不能仅靠点击事件触发
- 移动端文字折行时,连线高度需跟随节点垂直居中:
align-items: center+min-height: 2rem保底 - 步骤节点数量可能变化(如条件分支隐藏某步),DOM 必须同步增删,不能只靠 CSS 显隐——否则连线长度计算失准
最易被忽略的一点:步骤状态变更必须和表单校验强绑定。UI 走到第 3 步,但第 2 步字段为空,这种“假进度”不是体验问题,是数据完整性风险。校验逻辑必须在点击“下一步”时执行,不是提交时才触发。











