CSS计数器+display:table是唯一兼顾语义、响应式与超长序号的方案:.custom-ol设counter-set,li为table-row,::before伪元素作table-cell并设width:1px,使序号列自适应宽度、文本对齐干净。

直接用 ol 默认行为就能自适应内容宽度,但“自适应”不等于“缩进合理”——真正卡住你的不是宽度,而是序号和文本的对齐逻辑。
为什么 ol 的 padding-inline-start 不能随便设为 0
浏览器给 ol 默认加了约 40px 左侧内边距,目的是给序号留空间。直接写 padding-inline-start: 0 看似“让内容贴左”,实则会触发两个问题:
- 序号(尤其是三位数以上)被裁切在容器外,视觉消失
- 多行文本第二行起始位置与第一行不对齐,出现“悬空缩进”
- 屏幕阅读器仍读序号,但视觉错位导致可访问性降级
list-style-position: inside 看似简单,实际限制多
这个属性把序号塞进内容盒子里,确实能避免裁切,但它有硬伤:
- 序号和文本共用同一行盒,超长序号(如
99999.)会直接挤压文本可用宽度 - 无法控制序号右对齐,数字越长,左侧空白越不一致
- 在
flex或grid容器中行为不稳定,部分浏览器忽略该声明
CSS 计数器 + display: table 是目前唯一兼顾语义、响应式与超长序号的方案
它不改 HTML 结构,不依赖 JS,且天然适配任意长度序号。关键在于用表格布局的列宽自适应特性“托住”序号:
立即学习“前端免费学习笔记(深入)”;
-
.custom-ol li设为display: table-row,让每个列表项成为一行 -
::before伪元素生成序号,设为display: table-cell,并加width: 1px -
width: 1px是触发点:它告诉浏览器“这列最小就 1px,其余由内容撑开”,序号多长,列就多宽 - 文本内容自动进入下一个
table-cell,不受序号宽度影响,换行对齐始终干净
最易忽略的一点是:counter-set 必须写在 .custom-ol 上,而不是 li;否则重置起点失效,比如从 start="100" 开始的列表会显示为 1. 而非 100.。



















