ol标签不支持任意字符串序号,需用CSS counter配合伪元素实现自定义;list-style-type仅支持预设编号类型;嵌套列表需多级counter控制;动态场景下JS生成更可靠。

ol 标签本身不支持任意字符串(如“第一步”“→”“✓”)作为序号,真要自定义,必须用 CSS counter 配合伪元素,或彻底放弃语义化改用 div + 手动编号。
用 list-style-type 控制基础编号样式
浏览器原生支持的编号类型有限,list-style-type 是最轻量的控制方式,但仅限于预设值:
-
decimal(1, 2, 3)——默认值,无需显式写 -
lower-alpha(a, b, c)、upper-alpha(A, B, C) -
lower-roman(i, ii, iii)、upper-roman(I, II, III) -
none:清空序号,为后续自定义腾出空间
注意:type 属性(如 )虽可用,但已被 HTML5 视为过时,优先用 CSS;且它无法实现前缀、图标、多级嵌套等复杂效果。
用 counter-reset + counter-increment 实现完全自定义
当需要“Step 1:”“→ 2.”“❶”甚至跳号(如 1 → 3 → 5)时,CSS 计数器是唯一可靠方案:
- 先在
ol上设counter-reset: step;初始化计数器 - 对每个
li设counter-increment: step;,触发递增 - 用
li::before { content: "Step " counter(step) ": "; }插入前缀+序号 - 若想从 100 开始,写
counter-reset: step 100;;若某项要跳两格,加counter-increment: step 2;
关键细节:list-style: none; 必须加在 ol 上,否则原生序号和伪元素会重叠;content 中不能直接写 HTML 标签, 这类需靠 font-weight 或 color 模拟。
嵌套列表中保持层级编号(如 1.1、1.2、2.1)
纯 ol 嵌套时,子 ol 默认重置为 1,无法自动继承父级编号。CSS counter 可解决:
- 父
ol设counter-reset: section;,子ol设counter-reset: subsection; - 父
li用counter-increment: section;,子li用counter-increment: subsection; -
li::before内写content: counter(section) "." counter(subsection) " "; - 注意:子
ol必须在父li内部,否则计数器作用域失效
别指望 value 属性或 start 能跨层联动——它们只影响单层,且不触发子层自动更新。
容易被忽略的渲染细节
序号不是文本节点,它不参与行高、垂直对齐或背景色继承:
-
li的padding-left要预留足够空间,否则自定义序号会被截断 - 给
li设background-color,::before生成的序号默认无背景,需单独加background或display: inline-block -
list-style-position: inside会让原生序号挤进内容流,但对counter无效——它的位置由::before的margin或position控制 - 移动端缩放时,小字号序号可能糊成一团,建议用
font-size: 0.9em而非固定像素值
真正麻烦的不是怎么写出来,而是当列表动态增删、服务端渲染与客户端 hydrate 不一致、或配合 contenteditable 时,counter 会完全失效——这种场景下,老老实实用 JS 生成序号更可控。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











