nav标签仅为语义化容器,实现折叠需css媒体查询控制显示/隐藏+javascript切换类名或checkbox纯css方案,配合aria属性保障无障碍,禁用display过渡而改用max-height/opacity动画。

nav 标签本身不支持折叠,得靠 CSS + JavaScript 配合
很多人以为 <nav></nav> 标签自带响应式菜单功能,其实它只是语义化容器,没有任何交互行为。真正实现“点击变三条横线、再点展开菜单”的效果,必须手动加 CSS 媒体查询控制显示/隐藏,再用 JS 绑定点击事件切换类名。
常见错误是只写 <nav></nav> 和一堆 <a></a>,没写 display: none 断点、也没给按钮加 aria-expanded,结果手机上菜单永远不出现,或屏幕阅读器无法识别状态。
- 响应式断点建议用
@media (max-width: 768px),覆盖主流小屏设备 - 折叠时隐藏菜单内容,但别用
visibility: hidden—— 它仍占布局空间,要用display: none或max-height: 0配合过渡 - 务必给汉堡按钮加
aria-label="打开导航菜单"和aria-controls="nav-menu",否则无障碍访问会失败
用 checkbox 模拟开关比 JS 更轻量且无需初始化
很多教程一上来就写 document.getElementById 和 addEventListener,但纯 CSS 方案更稳定:把 <input type="checkbox"> 放在汉堡按钮前,用 label 关联它,再用 :checked ~ ul 选择器控制菜单显隐。这样页面加载瞬间就能响应,也不怕 JS 加载失败导致菜单卡死。
注意点:
-
<input>必须放在<nav></nav>外部或顶部,且不能被display: none彻底隐藏(可用position: absolute; left: -9999px) - 菜单
<ul></ul>要紧跟在<input>后面,才能用~通用兄弟选择器匹配 - 移动端点击区域要够大,
label的padding至少设为12px,避免误触
折叠菜单的 CSS 过渡动画别直接 transition display
display 属性无法做 CSS 过渡,硬写 transition: display 0.3s 是无效的。想实现淡入滑下效果,得换思路:
- 用
max-height+overflow: hidden控制高度变化(注意设一个足够大的max-height值,比如500px,否则内容多时会被截断) - 配合
opacity和transform: translateY()做组合动画,视觉更自然 - 如果菜单项有子菜单,别用
height: auto—— 它无法过渡,得用 JS 动态读取scrollHeight再赋值,或者改用grid/flex的gap和scale动画替代
移动端点击后菜单不收起?检查 focus 状态和点击穿透
常见现象:点开菜单后,再点某个 <a></a> 链接,菜单没自动关闭。原因通常是 JS 里没监听链接点击事件,或用了 preventDefault() 却忘了调用 closeMenu()。
更隐蔽的问题是 iOS Safari 的点击穿透:汉堡按钮用 label 包裹 input,但点击区域重叠时可能触发两次事件,导致菜单闪退。解决方案:
- 给菜单
<ul></ul>加pointer-events: none,内部<a></a>单独设pointer-events: auto - JS 中用
event.stopPropagation()防止冒泡,尤其当菜单嵌在position: fixed的父容器里时 - 真机测试时开启 Safari 的「停用 JavaScript」选项,确认 checkbox 方案是否仍能基础展开/收起
实际项目里,最易被忽略的是键盘操作支持 —— 用户按 Tab 键聚焦到汉堡按钮后,回车或空格应能切换菜单,这需要监听 keydown 并判断 event.key === 'Enter' || event.key === ' '。没有这个,WCAG 2.1 就算不过。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











