最稳方案是flex-wrap: wrap + flex: 1 1 min-width + 媒体查询;需设min-width: 0、修正white-space、用max-width断点、加viewport meta、确保JS类名与CSS一致,并避免display: none影响可访问性。

直接说结论:用 flex-wrap: wrap + flex: 1 1 min-width + 媒体查询是最稳的组合,比硬写 grid-template-columns 更易控断点、更少 Safari 错位问题。
flex-wrap: wrap 为什么加了也不换行?
不是属性没生效,是子项默认 min-width: auto,死守文字宽度,宁可撑破容器也不折。Flexbox 不会主动压缩内容,它只按你给的约束算空间。
- 给每个导航项(比如
.nav-links li)显式加min-width: 0,允许文本折行或缩放 - 删掉
white-space: nowrap—— 它锁死单行,换行直接失效 - 用
flex: 1 1 auto替代flex: 1,前者允许收缩,后者强制拉伸填满 - 检查父容器有没有
overflow: hidden或max-width冲突,它们会截断换行逻辑
@media 断点设成 768px 却在 iPad 上不生效
iPad 横屏时 CSS width 媒体查询可能匹配到 1024px,但实际 layout viewport 是 768px —— 因为没声明 <meta name="viewport">,浏览器回退到桌面视口。
- 必须加
<meta name="viewport" content="width=device-width, initial-scale=1">,否则所有max-width查询都不可靠 - 优先用
max-width而非max-device-width,后者已被 Chrome/Safari 弃用 - 真机调试别信 DevTools 的“iPad”预设,手动输入 viewport 尺寸(如 768×1024)更准
- 断点值建议实测:缩小桌面浏览器窗口,看导航何时开始挤压,记下那个像素值,比抄 768px 更靠谱
汉堡菜单点击后不收起,JS 绑定常见失效点
不是 JS 写错了,而是 DOM 状态和 CSS 类名没对上。最隐蔽的是:JS 切换 .active,但 CSS 里写的是 .menu.show —— 名字不一致,样式根本不会应用。
立即学习“前端免费学习笔记(深入)”;
- 确保 JS 修改的是同一个节点的 class,比如
document.querySelector('.nav-links').classList.toggle('active') - CSS 中必须有对应规则:
.nav-links.active { display: flex; },不能漏掉.active - 别用
display: none隐藏菜单 —— 它会让屏幕阅读器跳过整个导航;改用position: absolute; clip-path: inset(100%);或配合aria-hidden - 给汉堡按钮加
aria-expanded="false",点击后同步更新该属性值,否则辅助技术无法感知状态变化
真正卡住人的,从来不是 flex-wrap 怎么写,而是 Safari 对嵌套 flex 容器中 min-width 和 em 单位的解析偏差,以及类名拼写差一个字母就全白搭——这些细节不盯住,再漂亮的代码也跑不起来。


















