ul和ol嵌套合法但必须将子列表完整置于li内,否则dom结构断裂、编号重置;多级编号如“1.1”需css counters实现,list-style-type仅作用于单层且不继承。

ul 和 ol 嵌套本身完全合法,但浏览器不会自动产生“1.1”“A.2”这类编号——结构对了,样式和编号得靠 CSS 主动控制;写错位置(比如子列表没包在 li 里),DOM 就已经不是你想要的嵌套了。
子列表必须完整写在 li 标签内部
这是所有问题的起点。浏览器只认「ol 或 ul 是某个 li 的直接子元素」这种结构。一旦漏掉 li,哪怕视觉上像嵌套,实际解析结果就是两个并列列表。
- 错误写法:
<ol> <li>第一步</li> <ol><li>子步骤</li></ol> </ol>—— 内层ol不在任何li里,浏览器会自动闭合外层ol,再开一个新ol - 正确写法:
<ol><li>第一步<ol><li>子步骤</li></ol> </li></ol>—— 内层ol完整包裹在<li>...</li>中 - 验证方式:用开发者工具选中内层
ol,往上查父节点,必须能一路回溯到某个li,再回到外层ol或ul
list-style-type 只作用于当前层,不继承也不拼接
给外层 ol 设 list-style-type: upper-alpha,内层 ol 不会变成 “A.1”;它仍从 1 开始,且默认用 decimal。想让每层符号不同,得手动指定:
-
ol默认是数字,ol ol建议设lower-alpha,ol ol ol可设lower-roman -
ul的有效值只有disc、circle、square;混用时别指望子ul自动变空心圆——它永远是实心圆,除非你显式改 - 别用
type="A"属性替代 CSS:它已被废弃,且对嵌套子列表完全无效
实现 “1.1”“1.1.1” 编号必须用 CSS counter
浏览器没有内置多级序号逻辑。counters() 是唯一可靠方案,关键在重置时机和命名隔离:
- 每层
ol都要显式写counter-reset: section;,否则子层计数器不会初始化 - 用不同名字区分层级,比如
section/subsection/subsubsection,避免互相覆盖 - 示例片段:
ol { counter-reset: section; } ol li { counter-increment: section; } ol li::before { content: counters(section, ".") ". "; } ol ol { counter-reset: section; } - IE10 及更早版本不支持
counters(),如需兼容,只能降级为静态文本或 JS 补充
缩进异常不是 HTML 错,是 padding-left 累加导致的
浏览器默认给每个 ul 和 ol 加约 40px 的 padding-left。嵌套两层就是 80px,三层 120px……看着歪,其实是盒模型叠加。
- 别用
text-indent:它只动第一行,对多行li完全无效 - 推荐统一重置:
ul, ol { padding-left: 2rem; },再用ol ol, ul ul { padding-left: 1.5rem; }微调 - 如果项目用了
normalize.css或其他 Reset,先查它对ul/ol的padding设置,再决定是否覆盖 - 调试时直接看 Elements 面板的 Computed Styles,比猜快得多
最常被忽略的是语义合理性:嵌套不是为了缩进好看,而是表达“某一项的展开说明”。超过三层后,屏幕阅读器播报容易混乱,DOM 深度也影响 JS 查询准确性——别为了技术可行而硬套三层以上。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











