HTML原生<progress>标签不能用作步骤指示器,因其仅表示任务完成百分比,缺乏步骤语义和可访问性;应使用<ol>+aria-current="step"实现语义化步骤导航,配合CSS伪元素定制样式并确保键盘焦点管理。

HTML 原生 <progress> 标签不能当步骤指示器用
它只表示「任务完成百分比」,不是「当前第几步 / 共几步」。浏览器渲染的是进度条,没有步骤点、文字标签、可点击状态,也不支持自定义 step 节点。强行塞 value 和 max 模拟步骤(比如 value="2" max="5")会导致语义错误、屏幕阅读器误读、无障碍失败。
用 <ol> + aria-current 实现真正语义化的步骤导航
这是 WCAG 推荐做法:有序列表天然表达步骤顺序,aria-current="step" 明确标出当前项,配合 CSS 可完全自定义外观。
常见错误现象:
– 直接用 <div> 堆步骤,丧失语义和键盘导航能力
– 忘记加 aria-current,屏幕阅读器无法告知用户“现在在第几步”
– 用 tabindex="0" 给非交互元素加焦点,但没处理 Enter/Space 响应
- 每个步骤用
<li>,不要拆成多个<div> - 当前步骤的
<li>加aria-current="step",其他不加 - 如果步骤可点击跳转,确保用
<a>或带role="button"+ 键盘事件的<li> - 用
counter-reset和::before生成序号,避免硬编码数字
<ol class="stepper"> <li>填写信息</li> <li aria-current="step">验证邮箱</li> <li>设置密码</li> </ol>
CSS 控制步骤点样式时,别依赖 list-style-type
它只能改序号类型(如 decimal、lower-alpha),没法做圆点+连线、图标替换、状态色块等现代 UI。必须用 ::before + 自定义伪元素。
立即学习“前端免费学习笔记(深入)”;
容易踩的坑:
– 用 background-image 替换步骤点,但没设 width/height 导致布局塌陷
– 连线用 border-left,结果在第一个步骤上也显示了多余线条
– 没给 aria-current="step" 对应的 ::before 单独写样式,状态视觉反馈缺失
- 用
counter-increment配合content: counter(step)生成动态序号 - 连线用
position: absolute的伪元素画,避开<li>流式布局干扰 - 为
[aria-current="step"]::before单独设置背景色和图标 - 移动端注意触控目标至少 44×44px,别让小圆点太难点
JavaScript 控制步骤切换时,只更新 DOM 属性,不重绘整个列表
步骤变化本质是状态同步问题,不是 UI 重建问题。每次跳步只要移除旧的 aria-current、加上新的即可,没必要清空 <ol> 再 innerHTML 一遍。
性能影响:
– 频繁 innerHTML 会销毁子节点事件监听器,导致按钮失灵
– 失去浏览器对 <ol> 的原生计数缓存,长步骤列表滚动卡顿
– SSR 渲染后 JS 注入又重绘,出现闪烁
- 用
document.querySelector('[aria-current="step"]')找当前项,.removeAttribute('aria-current') - 新步骤节点用
.setAttribute('aria-current', 'step') - 如果要高亮对应表单区域,用
id关联,而不是靠 class 名硬匹配 - 避免在
click回调里直接操作style,优先走 CSS class 切换
最常被忽略的一点:步骤变更后,焦点必须手动移到新步骤项或其内部可聚焦元素上,否则键盘用户会迷失在页面空白处。



















