bootstrap 5 原生进度条应通过预设 css 类(如.step-1-active)控制宽度,js 仅切换类名;多步骤表单用 visibility: hidden + position: absolute 隐藏非当前页以保表单状态;“下一步”按钮启用须基于 currentstepelement.checkvalidity() 验证,而非步骤序号;移动端步骤导航需 flex-wrap 或隐藏滚动条并加 touch-action: pan-x。

用 bootstrap 原生类实现进度条,别写 JS 控制宽度
Bootstrap 5 自带的 .progress 和 .progress-bar 就够用了,不需要手动计算百分比或监听步骤变化来改 style="width: xx%"。关键是把进度逻辑交给 CSS 类控制,JS 只管切换「当前步骤」状态。
常见错误是直接操作 progress-bar 的 style.width,结果响应式失效、动画卡顿、回退时宽度不同步。正确做法是给每个步骤对应一个固定 class(比如 step-1-active),用 CSS 预设所有进度状态:
.progress-bar.step-1-active { width: 25% }
.progress-bar.step-2-active { width: 50% }
.progress-bar.step-3-active { width: 75% }
.progress-bar.step-4-active { width: 100% }
JS 只需在切换步骤时更新 progress-bar 的 class:
document.querySelector('.progress-bar').className = 'progress-bar step-2-active';
步骤导航栏和表单页要联动,但别用 display: none 切换
多步骤表单里,用户点击顶部步骤点(如“联系信息”“支付方式”)应该跳转到对应表单页,同时高亮该步骤。如果用 display: none 控制整个 .tab-pane 显隐,会导致表单验证状态丢失、焦点重置、屏幕阅读器识别异常。
推荐用 visibility: hidden + position: absolute 隐藏非当前页,保持 DOM 存在和表单字段状态:
-
.step-pane默认设为position: absolute; visibility: hidden; top: -9999px - 当前步骤的 pane 加
.active类,覆盖为visibility: visible; top: 0; position: relative - 所有
input始终保留在 DOM 中,required、value、validity不会重置
上一步/下一步按钮的可用状态必须由表单验证驱动,不是靠步骤序号
很多人用 if (currentStep > 1) enablePrevBtn() 这种纯序号判断,结果用户没填完当前页就点「下一步」,按钮却能点——体验断裂。真实逻辑应该是:「下一步」是否启用,取决于当前步骤内所有 required 字段是否通过 checkValidity()。
实操建议:
- 每次点击「下一步」前,调用
currentStepElement.checkValidity(),失败则reportValidity()并阻止跳转 - 「上一步」始终可用(除非是第一步),不用验证
- 最后一步的「提交」按钮,应绑定
form.submit(),而非自定义 click handler,避免绕过原生验证
注意:Bootstrap 的 .was-validated 类要在表单 submit 后才生效,所以不要依赖它做实时禁用判断。
移动端步骤指示器要可滚动,且禁止用 overflow-x: auto 硬截
小屏下步骤导航栏(如 5 个步骤横向排列)容易溢出。直接加 overflow-x: auto 会让滚动条遮挡文字、无法点击中间步骤、iOS Safari 滚动不灵敏。
更稳妥的做法:
- 用
flex-wrap: wrap让步骤在窄屏自动换行(适合 ≤3 步) - ≥4 步时,用
scrollbar-width: none+-webkit-scrollbar: none隐藏滚动条,再加touch-action: pan-x保证手势流畅 - 关键:给每个步骤项加
flex-shrink: 0,防止被压缩变形
别忘了用 @media (max-width: 576px) 单独处理移动端字体大小和 padding,否则小屏点不准。
进度条本身不是难点,难的是让每一步的验证、状态、可访问性都对齐真实用户操作路径。最容易被忽略的是表单字段的 DOM 存活状态和移动端 touch 行为兼容性。











