必须用 input[type="checkbox"] + :checked 控制主菜单显隐,因其在 JS 失效时仍保证基础可用性;子菜单须嵌套于对应 li 内,用 :has() 精准控制展开,避免语义断裂与键盘导航失效。

菜单项太多导致移动端导航栏撑出屏幕、点击区域重叠、键盘焦点跳过子项——根本不是“加个汉堡图标”就能解决的,得从结构源头控制层级和状态同步。
为什么纯 HTML + 媒体查询无法让多菜单自动折叠
HTML 的 <nav></nav>、<ul></ul> 标签本身不带折叠逻辑,@media 只能决定“什么时候隐藏”,但不能响应“用户点一下怎么展开”。常见错误是:小屏下给 .nav-menu 加了 display: none,却没配任何状态触发机制,结果菜单永远不可见。
- 仅靠
@media (max-width: 768px)隐藏菜单,不提供显隐开关 → 用户点汉堡无反应 - 用
div或button当开关,CSS 无法监听其点击后状态 →:hover或:active不可靠,且不支持键盘Enter触发 - 把子菜单(如
<ul class="sub-menu"></ul>)放在父<li>外面或平级 → 屏幕阅读器读不出父子关系,Tab键会跳过
必须用 input[type="checkbox"] + :checked 控制主菜单显隐
这是目前唯一能在 JS 失效时仍保证基础可用性的方案。浏览器原生支持 checked 状态,CSS 可直接捕获并联动样式,无需脚本兜底。
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
-
input必须在.nav-menu元素之前,且同级,才能用~选择器精准命中:input:checked ~ .nav-menu -
label必须包裹或通过for关联该input,确保 iOS 触控热区 ≥ 44px - 避免写
display: none→display: block切换,它不支持transition;改用max-height: 0/max-height: 300px+overflow: hidden - 若菜单项动态增减,别硬写死
max-height: 300px;预估最大高度,或保留 JS 补充计算(但基础功能不依赖它)
多级子菜单必须嵌套在对应 <li> 内部,用 :has() 控制展开
子菜单不是“可有可无的装饰”,而是语义结构的一部分。错误地用 div 堆叠或外置,会导致键盘导航断裂、屏幕阅读器静默、移动端定位偏移。
立即学习“前端免费学习笔记(深入)”;
- 子菜单必须是
<li class="menu-item"><ul class="nested">...</ul></li>,即li > ul.nested结构 - 展开逻辑不能写成
.menu-item.active ul { display: block; }→ 这会让所有深层子菜单同时弹出 - 正确写法:
.menu-item:has(> .nested).active > .nested { display: block; },:has()在 Chrome/Safari 已稳定,IE 不支持需降级为class="has-submenu" - 避免用
visibility: hidden替代max-height: 0→ 它仍占布局空间,会导致点击区域错位、焦点框偏移
真正难的不是让菜单“动起来”,而是让它在 JS 加载失败、屏幕阅读器启用、键盘导航、缩放 200%、甚至网络极慢时,依然能被用户识别、抵达、操作——这些细节藏在 HTML 结构顺序、CSS 选择器精度和属性语义里,而不是动画时长或图标旋转角度中。


















