多级菜单HTML结构必须用包裹,子菜单严格嵌套为的直接子,禁用隔断;须用:focus-within实现无障碍展开,多列用column-count+float:left布局。

多级菜单的HTML结构必须语义清晰,<nav></nav> 和 <ul></ul> 嵌套不能乱
浏览器和屏幕阅读器依赖语义化标签识别导航层级。错误写法比如把二级菜单直接塞进 <div> 或用多个平级 <code><ul></ul> 并列,会导致键盘焦点跳转异常、无障碍支持失效,且后续CSS控制子菜单显隐会更难。
正确结构应严格嵌套:
<nav role="navigation">
<ul class="menu-level-1">
<li><a href="#">首页</a></li>
<li>
<a href="#">产品</a>
<ul class="menu-level-2">
<li><a href="/prod/a">A系列</a></li>
<li><a href="/prod/b">B系列</a></li>
</ul>
</li>
</ul>
</nav>
-
role="navigation"是辅助技术识别关键导航区域的必要属性 - 每层
<ul></ul>必须是上层<li>的直接子元素,不可跨级或并列 - 避免在
<li>内混用<div> 包裹链接——它会破坏 <code>:hover/:focus-within的触发链:focus-within是现代多级菜单展开的核心,别再只靠:hover纯
:hover在触屏设备(包括平板、折叠屏、Win10/11触控模式)下完全失效;而 JavaScript 控制又容易引入焦点管理漏洞。CSS 的:focus-within提供了零 JS、可访问、响应式的展开逻辑。关键写法:
立即学习“前端免费学习笔记(深入)”;
Convert Markdown To HTML And PDF - Markdown和HTML、PDF互转下载实现 Markdown↔ HTML 互转,支持导出 PDF,用于用户请求的文档格式转换。
.menu-level-1 li:focus-within > .menu-level-2 { opacity: 1; visibility: visible; transform: scaleY(1); }- 父
<li>获得焦点(例如 Tab 进入链接后按 → 键,或点击触发),其内部任意可聚焦元素(如<a></a>)激活:focus-within - 必须配合
visibility: hidden+transform: scaleY(0)做初始隐藏,仅用display: none会让:focus-within失效 - 移动端 Safari 对
:focus-within支持良好(iOS 15.4+),但旧 Android WebView 需降级为 JS 监听click+focus
多列子菜单不用 Flexbox,改用
column-count+float: left当二级菜单有 15+ 个项、内容高度不一(如带图标+多行文字),Flexbox 的
flex-wrap: wrap会水平铺满再换行,导致列高严重不均、底部留白难看。这不是 bug,是 Flexbox 的设计逻辑使然。真正适配“报纸式垂直流”的方案是:
.menu-level-2 { column-count: 3; column-gap: 1.5rem; } .menu-level-2 li { break-inside: avoid; float: left; width: 100%; }-
column-count让浏览器自动把<li>按内容长度垂直切分到指定列数,视觉对齐自然 -
float: left确保每个<li>在列内顶部对齐,避免因高度差异造成列间错位 -
break-inside: avoid防止单个<li>被强行拆到两列,破坏语义完整性 - 注意:IE 不支持
column-count,若需兼容 IE11,必须回退到 JS 分组 + 多个<ul></ul>并列
固定定位菜单要防滚动穿透,
position: fixed必须配top: 0和z-index后台系统常见「左侧菜单固定 + 主内容区滚动」布局。若只给菜单加
position: fixed,但没设top: 0,它可能随文档流偏移;若z-index不够高,会被弹窗、图表组件遮挡;更隐蔽的问题是:滚动主内容时,菜单下的背景会“透出”,尤其在 macOS Safari 中明显。- 固定菜单容器必须声明
top: 0(或bottom: 0)+left: 0(或right: 0),否则定位基准不可控 -
z-index建议 ≥ 1000,且确保所有同级覆盖层(如.modal,.tooltip)的z-index明确高于它 - 透出问题本质是合成层缺失,加
transform: translateZ(0)或will-change: transform可强制创建独立图层,彻底解决
:focus-within和column-count的组合使用——它们不冲突,但需要同时满足「语义结构正确」「初始状态用visibility控制」「浮动子项宽度设为100%」这三个条件,缺一就会导致菜单要么不展开,要么列错乱。 - 父


















