ol必须只包含li元素,其他内容会被浏览器移出结构导致编号不显示、DOM错乱或语义断裂,嵌套列表须在li内,跳号应使用CSS计数器或ARIA属性而非value。

ol 必须只包含 li,任何其他元素(包括纯文本、p、div)直接作为子元素都会被浏览器忽略或移出结构——这不是样式问题,是语义断裂。
为什么ol里直接写文字不显示编号
浏览器严格遵循 HTML 规范:ol 的合法直接子元素只有 li(以及 script、template 等极少数例外)。一旦出现违规内容:
-
<ol>第一步</ol>→ 编号完全不渲染,控制台无报错,但 DOM 中该文本游离在列表之外 -
<ol><p>第一步</p></ol>→p被提升到ol外部,ol变成空容器 - 嵌套时漏掉
li包裹,比如<ol><ol><li>子项</li></ol></ol>→ 内层ol被解析为兄弟节点,父子关系丢失
li 必须显式闭合,别依赖浏览器自动修复
虽然现代解析器会尝试补全,但后果不可控:
-
<ol><li>第一项<li>第二项</ol>→ 第二个li可能被识别为第一个的子内容,DOM 层级错乱 - Vue/React 模板中直接报编译错误;EJS 或 PHP 服务端渲染时,条件分支漏写
</li>会导致整段 HTML 树断裂 -
document.querySelectorAll('li')返回数量少于预期,或把文本节点误判为li - W3C Validator 明确警告,CI 流水线启用校验时会失败
嵌套必须落在li内部,不能平级拼接
多级编号(如 “34. …… a) ……”)靠的是 DOM 层级嵌套,不是多个 ol 并列:
立即学习“前端免费学习笔记(深入)”;
- 错误写法:
<ol start="34"><li>主项一</li><ol type="a"><li>子项</li></ol></ol>→ 内层ol被踢出外层ol,变成兄弟元素 - 正确写法:
<ol start="34"><li>主项一<ol type="a"><li>子项</li></ol></li></ol>→ 子ol完整包裹在某个li的起始与结束标签之间 - 子列表类型(
type="a")仅影响视觉样式,不改变语义顺序;若子项本身有执行先后逻辑(如“先 A 后 B”),就该用ol,而不是退化成ul
别用value模拟跳号,真要跳号得靠 CSS 计数器或语义标注
value 是局部覆盖,它不重置后续计数起点,且对可访问性无效:
-
<ol><li value="10">苹果<li>香蕉<li value="50">橙子</ol>→ 渲染为 10、11、50,但屏幕阅读器仍播报“第 1 项、第 2 项、第 3 项” -
start和reversed都只作用于整个ol元素,写在li上会被忽略 - IE11 及更早版本不支持
start和reversed;reversed在type="a"或type="i"下无效 - 需要语义上跳过前几项(如法律条文废止后接续编号),应配合
aria-posinset和aria-setsize手动标注,而非依赖value
最常被忽略的一点:列表结构一旦写错,后续所有 CSS 样式、JS 操作、无障碍补救都是在打补丁。第一行就该决定用 ol 还是 ul,而不是等出问题再回头改。



















