ul > li > ul 必须是直接子元素才能保证缩进和可访问性;正确结构为<li>文字<ul><li>子项</li></ul></li>,避免包裹在div等标签中,且需用margin-left、em单位及显式list-style-type确保跨浏览器一致性和语义正确性。

ul > li > ul 必须是直接子元素,否则缩进失效
浏览器只对合法嵌套的 ul 自动加 margin-left,前提是它必须是 li 的**直接子元素**。常见错误写法:<li>文字<div><ul><li>子项</li></ul></div></li>——ul 被包在 div 里,结构断裂,缩进消失,屏幕阅读器也读不出子列表。
正确写法只有这一种:<li>文字<ul><li>子项</li></ul></li>。检查 DOM 时,用浏览器开发者工具看 ul 是否紧贴在 li 开始标签后,中间不能插任何其他标签。
- 如果用了 CSS 框架(如 Bootstrap),确认没全局重置
ul ul { margin: 0; } - 父级若设了
display: flex或display: grid,会破坏块级流,导致内层ul不再继承默认缩进 - 用
ul > li > ul这类子选择器调试样式,比ul ul更精准,避免误命中深层嵌套
list-style-type 按层级显式设置,别依赖默认
浏览器对二级 ul 默认用 circle、三级用 square,但这个行为不保证跨浏览器一致,尤其在重置样式后完全不可靠。必须手动指定。
推荐写法:
ul { list-style-type: disc; }
ul > li > ul { list-style-type: circle; }
ul > li > ul > li > ul { list-style-type: square; }注意:用 > 是为了精确到“下一级”,避免 ul ul 同时匹配二级和三级,造成样式污染。
-
list-style-position: inside会让项目符号挤进文本区,视觉缩进变小甚至错位,多级列表一律用outside(默认值) - 若需中文编号(如“一、”“(一)”),不能只靠
list-style-type,得用 CSS 计数器 +::before - 混合嵌套时(
ol套ul),ol li ul这类组合选择器要提前测试,避免符号重叠或间距异常
缩进用 margin-left 而不是 padding-left
缩进本质是层级位移,不是内容内边距。用 padding-left 会让点击区域变宽、文本换行错位,且无法与项目符号对齐;margin-left 才是语义正确的做法。
立即学习“前端免费学习笔记(深入)”;
示例:
ul { margin-left: 1.5em; }
ul ul { margin-left: 1.8em; }
ul ul ul { margin-left: 2.1em; }数值递增,形成清晰视觉阶梯。不要用固定像素(如 20px),em 单位能随字体缩放保持比例。
- 若父容器有
overflow: hidden,过大的margin-left会导致子列表被裁剪,此时改用transform: translateX(...)更安全 - 移动端小屏下,多层缩进易撑破容器,建议用媒体查询逐步减小
margin-left值 - 避免对
li设置margin-left来模拟缩进——这会干扰list-style-position和可访问性播报
可访问性陷阱:嵌套层级不能靠 class 模拟
屏幕阅读器靠 HTML 结构识别“子列表”,不是靠 class 名。写 <li class="has-child">菜单</li><ul class="submenu">... 是无效的——ul 不在 li 内,就不是子列表,会被读作独立列表,失去层级关系。
真正需要交互的树形菜单(如可展开/折叠),必须用语义化结构:
<li>
<button aria-expanded="false">文档</button>
<ul>
<li>入门指南</li>
<li>API 参考</li>
</ul>
</li>然后用 JS 切换 aria-expanded 和 hidden 属性。
-
role="menu"和role="menuitem"仅用于模仿原生菜单控件,普通内容列表不用,否则干扰阅读器逻辑 - 用
tabindex="0"给可交互按钮加键盘焦点,但别给li加——它不是焦点目标 - 纯内容型多级列表(如文章大纲)不需要 JS,结构合法 + 语义正确就是最好的可访问性
ul 就没塞进 li 里。先用浏览器检查器确认 DOM 树是否干净,再调样式。



















