<ol>是唯一合理起点,必须配合aria-current="step"、可聚焦的<li>及语义化结构才能实现高可访问性;<progress>仅作视觉辅助,不可替代步骤数值提示。

纯 HTML 标签本身无法实现“高可访问性”的步骤条——<ol> 是必要基础,但必须配合 ARIA 属性和语义结构才能达标。只写 <ol><li>第一步</li></ol>,屏幕阅读器只会读“列表,1 项”,不会说明这是步骤流程、当前在哪步、是否完成。
为什么 <ol> 是唯一合理起点
浏览器和辅助技术对 <ol> 的原生支持远超 <ul> 或 <div>:它自带顺序语义、默认编号(即使被 CSS 隐藏)、键盘导航天然按序跳转。用 <ul> 或一堆 <div> 模拟步骤,等于主动放弃语义层,后续所有 ARIA 补救都事倍功半。
- 每个步骤必须是
<ol>的直接子元素<li>,不能嵌套在<div>或<span>里 - 不要用
list-style: none后再靠伪元素重绘编号——这会让编号从可访问树中消失;应保留计数逻辑,仅视觉隐藏 - 若需多级步骤(如“2.1.3”),必须用 CSS
counter-reset+counters(),不能依赖浏览器自动嵌套编号
aria-current="step" 必须加在当前 <li> 上
这是告诉屏幕阅读器“你现在正处在哪个环节”的最简有效方式。不加这个属性,用户根本不知道流程进行到哪了——尤其当步骤文字相似(如“填写信息”“确认信息”“提交信息”)时,仅靠视觉色块毫无意义。
- 只给当前活跃的
<li>加aria-current="step",其他步骤不加;不要用aria-hidden="true"隐藏非当前项,那会切断导航流 - 避免和
role="tab"混用——步骤条不是标签页,aria-current比aria-selected更准确 - 服务端渲染时,该属性应由后端动态注入;前端 JS 切换步骤时,必须同步更新该属性,而非只改 class
进度数值不能只靠 <progress> 标签
<progress> 元素只表达“完成百分比”,不是“第几步 / 共几步”。它的 aria-valuenow 会被朗读为“进度 50%”,而非“步骤 2,共 4 步”,这对多步骤表单是误导。
立即学习“前端免费学习笔记(深入)”;
- 若需数值提示,用
<span>包裹文本(如<span>步骤 2,共 4 步</span>),并用aria-live="polite"包裹整个提示区域,确保切换时自动播报 -
<progress value="2" max="4">可以存在,但仅作视觉辅助;value 必须是数字,不能是字符串 "2" - 别用
<progress>控制步骤显隐或校验逻辑——JS 必须独立维护currentStep状态变量
键盘焦点必须可预测且不丢失
步骤条常被设计成“只读指示器”,但用户可能需要通过 Tab 键快速定位到当前步骤的表单字段。如果 <li> 不可聚焦、或焦点跳转后没落在对应内容区,就等于关闭了键盘用户的入口。
- 当前
<li>应设tabindex="0",确保能被 Tab 到;非当前项保持tabindex="-1"或不设 - 步骤切换后,焦点必须自动移到该步骤容器内第一个可交互元素(如输入框、按钮),不能停在
<li>自身 - 避免用
display: none隐藏非当前步骤内容——这会让键盘焦点“掉进黑洞”;改用visibility: hidden+position: absolute或 ARIAaria-hidden="true"配合inert属性(需检查兼容性)
真正难的不是写出带圆点和连线的步骤条,而是让每个属性、每个 tabindex、每个 aria-live 的触发时机都严丝合缝。稍有疏忽,视觉上完美的步骤条对屏幕阅读器用户来说就是一堵墙。



















