纯靠 flex 做不了折叠,必须配合 @media 查询 + display 切换或 JavaScript 控制显隐;flex 仅负责布局排列,折叠需媒体查询隐藏菜单、JS 切换类名实现点击展开,并注意小屏下 flex-direction、宽高、焦点管理等细节。
flex 实现折叠?直接说结论:纯靠 flex 做不了折叠,必须配合 @media 查询 + display 切换或 JavaScript 控制显隐。弹性盒子只管布局排列,不负责“收起来”这个交互行为。
常见误解是以为 flex-direction: column 或 flex-wrap: wrap 就能自动折叠,其实它们只是改变子元素排列方式,菜单项依然全部可见。
flex 适合组织导航项在横屏/竖屏下的对齐、间距、换行逻辑display: none 或 visibility: hidden 隐藏菜单容器.menu-toggle)和少量 JS 切换类名@media 控制导航显示状态的最小配置关键不是写多复杂的 CSS,而是明确断点和显隐逻辑。主流做法是在 max-width: 768px(平板窄屏)或 max-width: 480px(典型手机)下隐藏主菜单,只留一个汉堡按钮。
.nav-menu {
display: flex;
}
@media (max-width: 768px) {
.nav-menu {
display: none;
}
.nav-toggle {
display: block;
}
}
@media (min-width: 769px) {
.nav-toggle {
display: none;
}
}
注意:display: none 会彻底移除元素流内位置,比 visibility: hidden 更干净;但若想保留占位或做过渡动画,得改用 max-height + overflow: hidden 配合 transition。
CSS 本身没有“点击后切换状态”的能力(:checked 仅限表单控件,且需配合 隐藏处理)。所以实际项目中几乎都会遇到这些情况:
+ label 模拟开关:可行但语义弱、键盘导航支持差details/summary:语义好,但样式定制难,旧版 Safari 支持不稳定.nav-toggle 点击,切换 .nav-menu 的 is-open 类,再由 CSS 控制显隐或 transform 动画比如 JS 部分只需一行核心逻辑

document.querySelector('.nav-toggle').addEventListener('click', () => {
document.querySelector('.nav-menu').classList.toggle('is-open');
});对应 CSS 中定义 .nav-menu.is-open { display: flex; } 即可。
flex 还有什么坑?一旦进入手机展开态,flex 布局反而容易出问题——比如子项默认 flex: 0 0 auto,在竖排时可能撑宽容器、出现横向滚动条。
.nav-menu.is-open 加 flex-direction: column 后,记得设 width: 100% 和 box-sizing: border-box
a 标签若带 padding 或 margin,在小屏下易造成点击热区过小,建议统一用 min-height: 48px 保证触控友好@media 内重复写整套 flex 属性,优先复用基础类,只覆盖必要值(如 flex-direction、justify-content)最常被忽略的是焦点管理:JS 展开菜单后,应该把焦点移到第一个导航链接上,并在关闭时移回触发按钮,否则屏幕阅读器用户会迷失。