关键在于媒体查询需协同dom状态与布局机制:小屏下用display:none隐藏菜单,配合checkbox hack或类名切换控制显隐,并用max-height实现过渡动画,避免内联样式覆盖及visibility:hidden占位问题。

在 H5 中用媒体查询处理移动端小屏幕导航栏折叠,关键不是单纯“加断点”,而是让 CSS 媒体查询与 DOM 状态、布局机制协同生效。很多项目写了 @media (max-width: 768px) 却仍出现菜单挤成一行、汉堡图标不响应、展开后无法自动收起等问题——根源在于媒体查询只控制样式,不接管行为逻辑。
媒体查询必须配合 display 切换,而非仅 flex-wrap
flex-wrap: wrap 只是让 <li> 换行,所有导航项仍在文档流中渲染,小屏下容易撑高导航栏或触发横向滚动。真正折叠是让非核心内容“退出布局流”:
- 桌面端:`.nav-menu { display: flex }`,所有链接水平排列
- 小屏下(如
@media (max-width: 768px)):`.nav-menu { display: none }`,整个菜单容器隐藏 - 同时,把汉堡图标(
.menu-toggle)设为display: block,并确保它和菜单容器处于同一级 DOM 层级,便于后续用:checked ~ .nav-menu或 JS 控制显隐
汉堡图标的绑定方式决定是否纯 CSS 可控
若想零 JS 实现折叠,必须用 Checkbox Hack,且结构顺序不能错:
- HTML 必须是:
<input type="checkbox" id="nav-toggle"><label for="nav-toggle">☰</label><nav class="nav-menu">...</nav> - 隐藏 checkbox 推荐用
position: absolute; clip: rect(0 0 0 0),避免opacity: 0或visibility: hidden影响可访问性 - 小屏下激活菜单的 CSS 规则应写为:
#nav-toggle:checked ~ .nav-menu { display: block; },而不是靠 JS 切类名
屏幕尺寸变化时,要避免内联样式覆盖媒体查询
常见错误:JS 点击后直接 `.css("display", "block")`,导致即使窗口拉宽,菜单仍强制显示。正确做法是:
- JS 只负责切换类名,例如
document.body.classList.toggle("menu-open") - 媒体查询内定义该类的效果:
@media (max-width: 768px) { body.menu-open .nav-menu { display: block; } } - 这样当屏幕变宽,媒体查询失效,`.menu-open .nav-menu` 规则不生效,菜单自然回归桌面态的 flex 布局
过渡动画要用 max-height,别碰 height: auto
CSS 无法对 height: auto 做平滑过渡,强行写会跳变或无动画。安全做法是:
- 小屏下菜单设
max-height: 0; overflow: hidden; transition: max-height 0.3s ease; - 展开时设
max-height: 400px;(值需大于最大可能高度,但不宜过大,否则动画拖沓) - 避免用
visibility: hidden替代display: none,前者仍占空间,会导致父容器高度异常











