嵌套有序列表必须严格遵循html父子关系,子ol必须直接嵌套在父li内;type和start属性仅作用于当前ol,不继承;复合编号需用css counters()实现。

嵌套有序列表能正常工作,前提是结构合法;浏览器不认“看起来像嵌套”的写法,只认严格符合 HTML 规范的父子关系。
ol 必须直接包裹子 ol,不能放在外面
常见错误是把两个 <ol></ol> 并列写,比如先写一个 A. 的列表,再另起一个 <ol type="1"></ol> 放在它后面。这样浏览器会把第二个 <ol></ol> 当作全新列表,编号永远从 1 开始,而不是继承上一级的 B. 或 C.。
- ✅ 正确:子
<ol></ol>必须是父级<li>的直接子内容,不能脱离<li> - ❌ 错误:
<ol type="A"></ol> <ol type="1"></ol>—— 这是两个独立列表,毫无嵌套关系 - ⚠️ 注意:
<p></p>、<div> 或空行不会“隐式包裹”子列表,它们会直接破坏嵌套语义 <h3>type 属性只控制本层编号样式,不传递给子层</h3> <p><code>type属性(如type="A"、type="1")只影响当前<ol></ol>的编号类型,子<ol></ol>必须显式声明自己的type,否则默认用type="1"。浏览器不会自动“推导”子层该用什么类型。- 第一级用大写字母:
<ol type="A"></ol> - 第二级必须手动写:
<ol type="1"></ol>(不能省略) - 第三级同理:
<ol type="a"></ol>,否则仍是 1.、2.、3. - 如果某级想跳过编号(比如只做容器),就别用
<ol></ol>,改用<div> + CSS <h3>start 属性只对当前 ol 生效,不影响子 ol 起始值</h3> <p><code>start属性(如start="34")只设定当前<ol></ol>的第一个编号值,子<ol></ol>仍从 1 或 A 开始计数——它不会自动拼接成 34.1 或继承 34 作为前缀。- 想实现 34.1、34.2 这类复合编号,必须用 CSS
counters()函数,配合counter-reset和content - 单纯靠
start+ 嵌套<ol></ol>只能做到:外层 34、35、36,内层各自从 1 开始 -
value属性可用于单个<li>强制指定编号(如<li value="34.1">),但不可用于整层自动递增
用 counters() 实现 2.1、2.1.1 这类带点分隔的编号
当需要跨层级拼接编号(如外层
start="2"→ 内层显示 2.1、2.2),唯一可靠方式是放弃type和start的默认行为,改用 CSS 计数器接管全部逻辑。- 关键:给外层
<ol></ol>设置counter-reset: section,再用counter-increment: section控制递增 - 子层用
counters(section, ".")在::before中生成带点的前缀 - 必须配合
list-style: none关闭默认编号,否则会和伪元素冲突 - 示例片段:
ol { counter-reset: section; } ol li { counter-increment: section; } ol li::before { content: counters(section, ".") ". "; }
最容易被忽略的是:哪怕只是加了一个
<div> 包裹子 <code><ol></ol>,或者在<li>里多写了个<p></p>标签,都可能让子<ol></ol>脱离语义嵌套路径,导致计数器重置或样式失效。结构比样式更优先——先确保 DOM 层级正确,再谈编号怎么显示。 - 想实现 34.1、34.2 这类复合编号,必须用 CSS
- 第一级用大写字母:











