用媒体查询控制同一套html在不同断点下呈现不同布局,移动端用checkbox+label实现无js汉堡菜单,桌面端通过min-width断点启用flex横向导航,避免float和布局塌陷。

怎么让汉堡菜单在桌面端自动变成横向导航栏
关键不是“切换”,而是用媒体查询控制同一套 HTML 在不同断点下呈现不同布局。很多人误以为要 JS 切换 DOM 结构,其实纯 CSS 就能搞定,且更轻量、无闪屏。
HTML 必须保持语义化结构:用 <nav></nav> 包裹 <ul></ul> ,所有导航项写在同一个 <li> 列表里,不要为移动端/桌面端准备两套 DOM
移动端默认隐藏菜单( display: none 或 visibility: hidden ),用 checkbox + label 模拟点击展开(比 JS 更可靠,支持键盘焦点)
桌面端断点(如 min-width: 768px )里直接取消隐藏,并把 <ul></ul> 设为 display: flex ,<li> 设为 display: block 或 inline-flex
别用 float 布局横向菜单——它会脱离文档流,导致父容器高度塌陷,响应式下容易错位
为什么 checkbox + label 是比 JS 更稳的汉堡菜单方案
因为不依赖 JavaScript 执行时机,也不怕用户禁用 JS;同时天然支持空格/回车触发,无障碍体验更好。很多项目强行用 addEventListener('click') 绑定按钮,结果在 Safari 移动端或低配安卓机上点第一次没反应——其实是事件委托没处理好或点击穿透了。
<input type="checkbox" id="nav-toggle"> 放在 <nav></nav> 外层或顶部,不可见但可聚焦
<label for="nav-toggle"></label> 作为汉堡图标容器,用伪元素 ::before 画三横线
菜单列表用 ~ 或 + 选择器关联:比如 #nav-toggle:checked —— .nav-list 控制显示
记得加 transition: max-height 0.3s ease-in-out 配合 max-height 动画,别只用 opacity ——否则屏幕阅读器仍会读出隐藏内容
flex 布局下横向菜单常见错位和撑开问题
桌面端菜单突然换行、文字被截断、右侧图标跑飞……八成是 flex-wrap 和 flex-shrink 没控住。Flex 默认会压缩子项宽度来适应容器,但导航文字长度不一,压缩后易折行。
给 .nav-list 加 flex-wrap: nowrap ,强制单行
给每个 <li> 加 flex-shrink: 0 ,防止被压缩
如果用 justify-content: space-between ,注意首尾项间距过大,改用 space-around 或手动设 margin
字体用 font-variant-numeric: tabular-nums 对齐数字类菜单项(如“订单 2”),避免宽度跳变
移动端点击汉堡图标没反应?先查这三处
不是 JS 报错,大概率是 CSS 层叠或 HTML 结构出了问题。尤其在 Vue/React 项目里,开发者常把 label 和 input 分开放在不同组件,导致 for 关联失效。
检查 label[for] 的值是否严格等于 input[id] (大小写、空格、连字符都不能错)
确认 input 没被 display: none 或 visibility: hidden 彻底移出可交互范围——要用 position: absolute; opacity: 0; pointer-events: none;
看浏览器 DevTools 的 Elements 面板里, input 是否被其他样式(比如重置 CSS 里的 all: unset )清掉了 type="checkbox" 行为
事情说清了就结束。最常被忽略的是:桌面端菜单的 focus-visible 样式没做,导致键盘用户按 Tab 键时找不到当前焦点项。
标签: css




还木有评论哦,快来抢沙发吧~