纯css汉堡菜单需用:checked伪类配合checkbox输入框实现开关逻辑,html中input必须位于nav顶层且与ul同级,用~选择器控制显示,移动端适配需媒体查询和触摸友好尺寸。

用 :checked 配合隐藏单选框实现菜单开关逻辑
纯 CSS 实现响应式导航按钮(俗称“汉堡菜单”),关键不是靠 JS 控制 class,而是把一个不可见的 <input type="checkbox"> 或 <input type="radio"> 作为状态开关,再用 :checked 伪类去联动后续元素的显示/隐藏。注意:必须用 <input>,不能只靠 <label></label> 或 div 模拟——否则 :checked 根本不生效。
常见错误是直接给按钮加 :checked,但按钮本身不是表单控件;也有人误用 :focus 或 :hover 替代,结果在触屏设备上点一下就收起,体验断裂。
- 推荐用
<input type="checkbox" id="nav-toggle">,配合<label for="nav-toggle"></label>触发切换 -
id和for值必须严格一致,大小写敏感 - input 必须放在导航结构最外层(通常在
<nav></nav>内顶部),否则后续兄弟选择器(如~)无法选中菜单列表
用 ~(后续兄弟选择器)控制菜单列表显隐
HTML 中,菜单列表(<ul class="nav-list"></ul>)必须和 <input> 处于同一父容器内,且在它之后。这样才可以用 input:checked ~ .nav-list 精准定位并设置 display: flex 或 max-height 动画。
别用 +(相邻兄弟选择器),它只匹配紧挨着的下一个元素;而导航结构里 input 后面往往跟着 label(按钮),再后面才是 ul,所以必须用 ~。
- 若菜单列表被包裹在
<div> 里,选择器要写成 <code>input:checked ~ div .nav-list - 移动端默认隐藏菜单:给
.nav-list设display: none或max-height: 0,再在:checked ~规则里覆盖 - 想加展开动画?用
max-height+overflow: hidden比display更可靠,因为display无法过渡 - 菜单只在
max-width: 768px(或你定的断点)下用:checked控制;桌面端直接设display: flex,无需隐藏 -
<label></label>的点击区域至少 44×44px(iOS 最小触摸建议),用padding扩展,别只靠图标大小 - 避免在 label 上写
user-select: none,否则部分安卓浏览器会阻止触发 checkbox 切换 - 如果用了
position: fixed导航栏,确保.nav-list的z-index足够高,不然会被其他元素遮挡
移动端适配要点:媒体查询 + 触摸友好尺寸
响应式不是只靠 :checked 就完事。真正的问题在断点设计和点击区域。
为什么不用 :target 或 JS?这些替代方案的实际代价
有人试过用 <a href="#menu"></a> + ul:target,看似简洁,但问题明显:URL 地址栏会变化、后退键行为异常、SEO 可能误判为跳转锚点;JS 方案虽然灵活,但绕开了 CSS 原生状态管理,增加 bundle 体积,且在 JS 失效时整个菜单不可用。
:checked 是目前唯一能在无 JS、无障碍(支持键盘空格/回车切换)、无 URL 干扰前提下稳定工作的纯 CSS 开关方案。
真正的难点不在写法,而在 HTML 结构顺序和选择器作用域的精确控制——多一个嵌套层级,~ 就失效;少一个 id 匹配,点击就石沉大海。











