ol子元素只能是li,其他元素如p或div会导致HTML校验失败、屏幕阅读器误读、DOM结构非法及JS选择器失效;正确做法是所有内容必须包裹在li内,嵌套ol也须置于li中。

ol子元素只能是li,别往里塞p或div
浏览器会自动容错,把<p></p>或<div>包进<code><li>里再渲染,但HTML校验直接报错,屏幕阅读器可能跳过或误读内容。DOM结构非法,后续用JS操作querySelectorAll('ol > li')也拿不到你“以为”的项。
常见错误写法:<ol>
<p>第一步</p>
<p>第二步</p>
</ol>
正确做法:所有主干项必须包裹在<li>里,哪怕内容含段落、标题或图片——这些都可以合法放在<li>内部。
- 嵌套时,子
<ol></ol>必须放在某个<li>内,不能挂在父<ol></ol>下 - 若某步需多段说明,用
<p></p>包在<li>里,别靠换行硬凑 - 校验工具(如W3C Validator)会明确提示
"Element p not allowed as child of element ol"
start和reversed属性要慎用,动态场景优先CSS计数器
start和reversed是原生支持的属性,但只适用于静态内容。一旦用JS插入新<li>,编号不会自动重算;比如<ol start="5" reversed></ol>加了新项,序号就乱了。
立即学习“前端免费学习笔记(深入)”;
CSS counter-reset + counter-increment更可控,且能配合::marker做样式分离:
ol {
counter-reset: step;
}
ol li {
counter-increment: step;
}
ol li::marker {
content: counters(step, ".") ". ";
}-
start适合纯静态文档(如PDF导出前的HTML稿) -
reversed仅建议搭配start用于明确倒序(如“第5步→第1步”),别指望它响应数据更新 - 需要字母/罗马数字编号?用
list-style-type: lower-alpha或upper-roman,比type属性更可靠
清除默认样式时,padding-left和list-style都要处理
只写list-style: none,编号是没了,但左侧空白还在——Chrome默认padding-left: 40px,Firefox是2em,Safari又不一样。结果就是文字悬空、对不齐、缩进诡异。
安全写法是同步重置逻辑起始边距:
ol {
list-style: none;
margin-inline-start: 0; /* 推荐,适配LTR/RTL */
padding-inline-start: 0;
}- 别用
padding-left: 0硬写,方向固定,RTL页面会出问题 - 如果用Flex布局
<ol></ol>,记得给<li>设display: block,否则默认list-item可能干扰对齐 - 想保留缩进但不要数字?用
list-style-position: inside配合text-indent微调,比全清更精细
嵌套ol时,语义必须真实反映层级关系
嵌套不是为了视觉缩进,而是表达“子步骤属于该主步骤”。比如“3. 编译代码”下嵌套的“① 安装依赖”“② 运行构建”,必须写在第3个<li>内部,而不是另起一个<ol></ol>平级放。
否则大纲结构断裂,屏幕阅读器无法播报“这是第三步里的第一小步”,SEO也抓不到嵌套意图。
- 主列表用
<ol></ol>,子列表也用<ol></ol>(非<ul></ul>),除非子项确实无顺序依赖 - 避免“伪嵌套”:用CSS
margin-left模拟缩进而不用<ol><li><ol></ol></li></ol>,语义丢失不可逆 - 嵌套过深(>3层)要考虑是否真有必要——人脑难跟踪,可访问性也变差
真正容易被忽略的是:一旦用<div>或<code><p></p>替代<ol><li></ol>,补救成本远高于初始写对。语义不是“锦上添花”,它是DOM层面的契约——后续所有自动化处理(爬虫、读屏、AI摘要)都基于这个契约成立。



















