直接修改 ol.start 仅影响后续新增 li 的编号,不会重绘已有 li;要更新已有项需手动重写内容或用 CSS counter-reset 强制重计。

直接改 ol.start 就生效,但别指望它重排已有项
修改 ol 的 start 属性会立刻影响后续新增的 li 渲染编号,但**不会重绘已存在的 li 元素**。浏览器只在插入新 li 时按当前 ol.start 和已有项数量推导编号,不是“重新计数”。
常见误操作是:先渲染了 <ol start="1">
<li>A</li>
<li>B</li>
</ol>,再执行 ol.start = 100,结果仍是 “1. A”、“2. B”——因为 DOM 没刷新,序号早已生成。
- 想让已有项也更新编号,必须手动重写
li内容或用 CSScounter-reset强制重计 -
ol.start = "5"是合法的,但字符串会被隐式转为数字;ol.start = null或ol.start = ""会退化为 1 - 动态插入新
li时,它的编号 = 当前ol.start+ 已有li数量(不包括被display: none隐藏的)
start 和 value 混用会导致编号断裂
给某个 li 加 value 属性(如 <li value="20">)会覆盖该行编号,并让下一项从这个值 +1 开始递增——这和 start 的全局起点逻辑冲突。
例如:<ol start="10">
<li>A</li>
<li value="15">B</li>
<li>C</li>
</ol> 渲染为 “10. A”、“15. B”、“16. C”,而不是 “10. A”、“11. B”、“16. C”。一旦用了 value,start 对后续项就失效了。
立即学习“前端免费学习笔记(深入)”;
- 纯动态编号场景(如删除后重排),避免用
value,统一靠 JS 控制ol.start+ 重插li - 法律条文、标准文档等需局部跳号的场合才用
value,且要确认后续项是否真需要接续该值 - 用
value后再改ol.start,不会修复已错乱的编号链
用 CSS counter-reset 实现真正可控的动态重编号
当需要在不操作 DOM 的前提下让所有 li 实时响应编号变化(比如点击按钮切换起始值),counter-reset 是唯一可靠方案。它绕过 HTML 属性限制,完全由 CSS 触发重计算。
关键点:counter-reset: item 99 表示计数器初始值为 99,第一个 li::before 调用 counter(item) 就显示 100;改这个值就能批量刷新所有编号。
- 必须配合
counter-increment: item才能递增,否则所有项都显示同一数字 -
counter-reset可以设在任意父容器上,不限于ol标签本身,适合嵌套或多列表连续编号 - 屏幕阅读器仍按默认语义读取 1,2,3…,需额外加
aria-setsize和aria-posinset修正可访问性
嵌套 ol 中动态改 start 不会影响子列表
每个 ol 的 start 是独立的,改外层不会传导到内层。比如:<ol start="5">
<li>一级</li>
<ol><li>二级</li></ol>
</ol>,内层仍从 1 开始,哪怕你之后执行 outerOl.start = 100。
如果业务需要多级编号同步偏移(如 “3.1”、“3.2” 接着变成 “10.1”、“10.2”),仅靠 HTML start 无法实现,必须用 CSS 计数器并手动绑定层级关系。
- 不要试图用 JS 遍历所有子
ol并逐个设start,容易漏掉动态插入的节点 - 用
counter-reset在外层设section 2,内层用counter(section) "." counter(item),才能稳定产出 “3.1” 类格式 - 动态改编号时,CSS 方案比反复操作多个
ol.start更轻量、更易维护



















