html嵌套默认仅显示最内层阿拉伯数字编号,不支持“1.1”“1.2.1”等多级格式;需用css counter-reset、counter-increment及counters()函数手动实现,并配合list-style-type: none避免双重编号。

嵌套 <ol></ol> 的编号层级默认行为
HTML 原生的 <ol></ol> 在嵌套时会自动继承并递增编号层级,但**不会自动显示“1.1”“1.2.1”这类多级格式**——浏览器默认只渲染最内层的阿拉伯数字(如 1, 2, 3),外层编号被视觉隐藏,仅靠缩进体现结构。
这意味着写成这样:
<ol>
<li>第一项
<ol>
<li>子项一</li>
<li>子项二
<ol>
<li>孙项</li>
</ol>
</li>
</ol>
</li>
</ol>
实际渲染出来是三层独立的 1, 2, 3 —— 看不出隶属关系。这是初学者最容易误以为“已生效”的坑。
用 CSS counter-reset 和 counter-increment 实现真·多级编号
要得到类似“1 → 1.1 → 1.1.1”的效果,必须手动控制计数器。核心逻辑是:外层 <ol></ol> 定义主计数器,每层 <li> 触发自身层级计数,并在 ::before 中拼接上级编号。
- 给每层
<ol></ol>设置独立的counter-reset(如counter-reset: section、counter-reset: subsection) - 每层
<li>执行对应层级的counter-increment - 用
content: counters(section, ".")拼接所有父级计数器值(注意是counters(),不是counter())
示例关键 CSS:
ol { counter-reset: section; }
li { display: block; }
li::before {
counter-increment: section;
content: counters(section, ".") ". ";
}
ol ol { counter-reset: subsection; }
ol ol li::before {
counter-increment: subsection;
content: counters(section, ".") "." counters(subsection, ".") ". ";
}
⚠️ 注意:counters() 第二个参数是连接符,必须是字符串(如 "."),不能漏掉引号;且嵌套越深,CSS 规则越需显式分层,无法靠一层样式通吃。
list-style-type: none 必须配合 ::before 使用
一旦启用自定义编号,就得关掉默认列表标记,否则会出现双重编号(如 “1. 1. 文本”)。这步常被跳过,导致样式错乱。
- 所有参与自动编号的
<li>都要加list-style-type: none - 编号内容只能通过
::before生成,不能写在 HTML 里(否则无法联动计数器) - 若列表项含
<p></p>或其他块级元素,需确保::before的display为inline或inline-block,避免换行错位
兼容性与语义边界:别为了样式牺牲可访问性
这套 CSS 方案在 Chrome/Firefox/Safari(≥12)中稳定支持,但 IE 完全不支持 counters()。如果需兼容旧环境,得回退到 JS 生成编号或接受扁平化编号。
更重要的是:屏幕阅读器通常只读取 HTML 结构中的 <ol><li></ol> 层级,**不会解析 CSS 生成的编号文本**。所以“1.2.3”这种样式纯属视觉增强,不能替代正确的嵌套 DOM 结构。
真正容易被忽略的点是:当用 JS 动态插入新 <li> 时,CSS 计数器不会自动重算——它只响应初始渲染和 DOM 变更触发的重排,但不感知 JS 插入的内容是否该纳入计数。这时候得手动调用 element.outerHTML = element.outerHTML 强制重置,或改用 JS 维护编号逻辑。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











