因为li无状态属性且不响应交互,必须用checkbox控制展开收起;hover在触摸设备失效,js增加首屏负担;子菜单须为嵌套ul,缩进用padding-left累加并配border-left区分层级。

为什么不能直接用 li 做多级导航的“展开/收起”控制
因为 li 本身只是容器,没有状态属性,也不响应点击或勾选。想让它“记住是否展开”,必须借助可交互元素——比如 <input type="checkbox">。纯靠 :hover 在触摸设备上失效,且无法持久保持展开态;用 JS 虽然灵活,但增加首屏负担、破坏 SSR 可用性、还可能被禁用。
常见错误现象:
– 子菜单在手机上点一下就闪退
– 刷新页面后所有子菜单自动收起
– 键盘 Tab 焦点跳过子菜单项
– 屏幕阅读器读不出“设置菜单已展开”
- 每个子菜单必须是独立的
<ul></ul>,嵌在父<li>内部,不能用div替代 -
<input type="checkbox">必须和对应<ul class="submenu"></ul>是兄弟关系(中间不能插<label></label>或其他标签),否则:checked ~ .submenu选择器不生效 - 别给
li设position: relative后再用absolute定位子菜单——这会让焦点框偏移、屏幕阅读器丢失层级关系
li 的缩进与层级视觉必须用 padding-left,不是 margin-left 或 text-indent
缩进的本质是表达父子关系,不是排版装饰。用 margin-left 会把整个 li 推离文档流,导致 Tab 键顺序错乱;text-indent 只缩进第一行文字,对图标、复选框等内联内容无效;而 padding-left 是内边距,不影响布局流,且能保证焦点框包裹完整可点击区域。
实际层级缩进建议值:
– 一级菜单:padding-left: 1rem
– 二级菜单:padding-left: 2.5rem
– 三级菜单:padding-left: 4rem
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
- 每级缩进值需累加,不能固定为
1.5rem所有层级——否则视觉上分不清哪级是哪级 - 配合
border-left加不同灰度竖线(如#e0e0e0→#c5c5c5→#aaa),比纯缩进更易识别嵌套深度 - 不要用
transform: translateX()模拟缩进——它会让:focus-visible框错位,且影响无障碍 API 报告的位置信息
导航菜单里 li 必须包裹在 <nav><ul></ul></nav> 结构中,不能裸写
单独写一堆 <li>首页</li>
<li>关于</li> 是无效 HTML:浏览器会自动补全为 <ul>...</ul>,但语义丢失、ARIA 支持弱、SEO 权重低。搜索引擎和读屏软件依赖 <nav></nav> 明确识别导航区域。
典型结构错误:
– <div class="nav"><li>...(无语义,Tab 顺序混乱)<br>– <code><ul><li><p>首页</p></li></ul>(p 破坏列表项语义,焦点框包不住文字)
- 正确外层必须是
<nav aria-label="主导航"></nav>,加上aria-label让读屏软件知道这是什么导航 -
li内部直接放<a></a>或<button></button>,不要套span或div——否则键盘聚焦时 outline 不包围可操作内容 - 若某项是纯触发按钮(如“展开设置”),用
<button type="button"></button>,别用<a href="#"></a>,避免误触发页面跳转
移动端折叠子菜单时,@media 必须重置 display,不能只靠 visibility 或 opacity
用 visibility: hidden 或 opacity: 0 隐藏子菜单,会导致两个问题:一是仍占布局空间(下方内容不上移),二是键盘焦点仍能进入隐藏项(辅助功能违规)。真正“收起”意味着 DOM 元素不可见、不可聚焦、不参与布局。
关键 CSS 规则:@media (max-width: 768px) { input[type="checkbox"] + label + ul { display: none; } }
- 必须用
display: none,而不是display: block切换——否则在未勾选状态下,子菜单仍会渲染并占用内存 - 媒体查询断点建议设为
768px或em单位(如48em),避免硬编码像素值导致高 DPI 设备适配异常 - 别在移动端用
height: 0; overflow: hidden动画收起——动画期间height为 0 时,焦点仍可进入,且部分安卓 WebView 对overflow: hidden处理不稳定
:checked ~ ul 就彻底失效。










