ol标签语义化表达强制顺序,用于有先后/主次/依赖关系的列表;误用场景包括主观排序、视觉掩盖语义;嵌套需正确结构;自定义序号时须兼顾可访问性。

ol 标签就是干这个的——它天然表达「有先后、有主次、有依赖」的顺序,不是视觉上排个号,而是语义上声明“这件事必须在那件事之前”。
用 ol 而不是 ul 的关键判断点
当你心里冒出“第一步→第二步→第三步”或“最高优先级→次高→最低”这类线性逻辑时,ol 就该出场;如果只是并列罗列(比如“支持 Chrome、Firefox、Safari”),就该用 ul。浏览器和屏幕阅读器会据此读出“列表共 4 项,当前是第 2 项”,这对无障碍访问至关重要。
常见误用场景:
- 把“热门功能”“新上线”“推荐使用”这种主观排序硬套
ol—— 它们之间没有强制执行顺序,属于误导性语义 - 用 CSS 改成圆点后还留着
ol—— 视觉掩盖了语义,辅助技术仍会读作有序列表,造成认知冲突
type 和 start 属性的实际取舍
type 控制编号样式,start 控制起始数字,但它们不是总能一起用:IE 已淘汰,现代浏览器中 start 有效,但若同时设 type="a" 和 start="3",Chrome 会显示 c、d、e,而 Safari 可能仍从 a 开始。稳妥做法是:
- 纯数字序列:只用
start,不碰type - 字母/罗马序号:用
type,放弃start(或改用 CSScounter-reset精确控制) - 需要跳号(如“第1步→第3步→第5步”):别依赖
start,直接写三个li,靠内容说明,或用value属性逐项指定:<li value="5">最终验证</li>
嵌套优先级时的结构陷阱
真实业务中,“一级优先事项”下常有“子步骤”,这时容易写出错误嵌套:
<ol> <li>确认用户身份</li> <ol> <!-- ❌ 错:ol 不能直接放在 li 外面 --><li>检查手机号是否已绑定</li> </ol> </ol>
正确写法是把子 ol 放进父 li 内部:
<ol>
<li>确认用户身份
<ol>
<li>检查手机号是否已绑定</li>
<li>验证短信验证码</li>
</ol>
</li>
<li>加载用户配置</li>
</ol>
注意:嵌套后子列表默认继承父列表的 type,若需不同样式(如外层数字、内层字母),必须显式声明子 ol type="a"。
CSS 覆盖默认序号时的可访问性风险
用 list-style: none 配合伪元素自定义序号很常见,但若没同步处理 counter-increment 和 aria-label,屏幕阅读器会完全丢失顺序信息。最简补救:
- 保留原生
ol结构,仅用 CSS 隐藏默认序号:ol { list-style: none; } - 为每个
li添加aria-label:<li aria-label="第2步:验证邮箱">输入邮箱地址</li> - 或用 CSS counter 确保序号可读:
ol { counter-reset: step; } li::before { content: "第" counter(step) "步:"; counter-increment: step; }
真正难的不是让序号看起来漂亮,而是让“第几步”这个信息既对眼睛可见,也对语音可读、对键盘可导航——这恰恰是多数人忽略的临界点。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











