ol 的 type 属性仅控制单层编号样式,不支持父子层级继承与拼接,无法实现 1→1.1→1.1.1 类章节编号;必须用 CSS counter-reset/counter-increment 配合 counters() 实现多级自动编号。

ol 标签本身不支持“章节”语义,必须靠嵌套结构 + CSS 计数器实现层级编号(如 1 → 1.1 → 1.1.1),硬用 type 或 start 只能做单层切换,无法生成真正的章节式编号。
为什么 ol 的 type 属性做不了章节编号
HTML 原生 ol 的 type(如 A、a、i)只控制当前层的符号类型,不感知父级编号,也不自动拼接前缀。比如嵌套两层 <ol type="1"><ol type="a">,第二层永远从 a. 开始,不会变成 1.a. 或 1.1.a. —— 这不是 bug,是设计如此。
- 浏览器对
type的支持仅限于五种基础值:1、a、A、i、I - 多层嵌套时,每层
ol独立计数,父子间无继承关系 -
value属性只能手动设某一项的值,无法动态绑定上级编号
CSS counter-reset + counter-increment 是唯一可靠方案
要生成 1 → 1.1 → 1.1.1 这类章节编号,必须放弃纯 HTML 属性,改用 CSS 计数器。核心是为每一层定义独立计数器,并在子层中用 counters() 拼接。
- 顶层
ol:设置counter-reset: section,counter-increment: section - 第二层
ol:设置counter-reset: subsection,并用::before { content: counters(section, ".") ". " } - 第三层同理,再加一个
subsubsection计数器 - 注意:
counters()第二个参数是分隔符,必须是字符串字面量(如"."),不能是变量
ol { counter-reset: section; }
ol li { counter-increment: section; }
ol li::before { content: counters(section, ".") ". "; }
ol ol { counter-reset: subsection; }
ol ol li { counter-increment: subsection; }
ol ol li::before { content: counters(section, ".") "." counters(subsection, ".") ". "; }
嵌套结构必须严格符合 HTML 规范
章节列表的 DOM 结构出错,CSS 计数器就全乱——子 ol 必须写在父级 li 内部,不能平级放在父 ol 外面。
立即学习“前端免费学习笔记(深入)”;
- ✅ 正确:
<li>第一章<ol><li>1.1节</li></ol></li> - ❌ 错误:
<li>第一章</li><ol><li>1.1节</li></ol>(子列表脱离父项容器) - 错误结构会导致计数器重置、缩进错位、屏幕阅读器无法识别层级
- 检查方法:用浏览器开发者工具看
li是否真正包裹了子ol
实际部署时容易被忽略的兼容性点
counters() 在所有现代浏览器中都可用,但有两个隐蔽坑:
- IE 完全不支持
counters(),若需兼容,得回退到 JS 动态注入编号(不推荐) - 某些旧版 Safari 对嵌套过深(≥4 层)的
counters()渲染异常,建议限制在 3 层内 - 如果章节标题里含
<h2>等块级元素,::before会出现在块元素上方导致布局断裂,此时应把编号逻辑移到<span class="number">中用 JS 或服务端渲染



















