双排横向菜单核心写法是ul设display: flex + flex-wrap: wrap,清除默认样式,li用flex: 1或min-width控制尺寸,容器设max-width触发自然折行;二级菜单需一级li加position: relative,子ul用position: absolute + display: flex横向展开。

ul + flex 实现双排横向菜单的核心写法
双排横向菜单不是“两行 ul”,而是单个 ul 内部的 li 自动折行为两行,本质是弹性容器换行布局。关键不在嵌套结构,而在 flex-wrap: wrap 和容器宽度控制。
常见错误是手动拆成两个 ul,导致语义断裂、响应式错乱、JS 控制困难。正确做法是让一级 ul 承担全部菜单项,靠 CSS 触发自然折行:
-
ul设display: flex+flex-wrap: wrap,清除默认list-style、padding、margin -
li不设固定宽,用flex: 1 1 auto或min-width控制最小尺寸(如min-width: 120px) - 容器(比如
nav)设明确宽度或最大宽度,例如max-width: 960px,否则在大屏下永远单行 - 避免对
li设width: 50%——它不随内容伸缩,小屏下会强制挤成一行再溢出
双排菜单中 hover 下拉子菜单的定位陷阱
二级菜单要横向铺开(而非竖向下拉),且必须精准出现在对应一级项下方,position: relative 必须落在一级 li 上,不是 ul 或 nav。
典型错位现象:ul 里所有 li 折成两行后,第二行的子菜单飘到页面顶部或左侧——这是因为父 li 没设定位上下文,子 ul 默认相对 body 定位。
立即学习“前端免费学习笔记(深入)”;
实操要点:
- 给每个一级
li加position: relative(哪怕它已折行) - 子
ul设position: absolute+top: 100%+left: 0,确保紧贴父项底部 - 若需子菜单也横向排列,子
ul加display: flex+flex-direction: row,别用inline-block避免间隙 -
z-index: 1000必加,否则可能被轮播图、弹窗等覆盖
移动端双排菜单的滚动与折叠取舍
小屏下双排菜单极易内容溢出,但直接折叠为汉堡菜单会丢失“双排”特性。实际项目中更可行的是:窄屏启用横向滚动,中屏以上才允许折行。
纯 CSS 方案需外层包裹并控制溢出:
- 用
div包住nav > ul,设overflow-x: auto+white-space: nowrap -
ul改用display: inline-flex(非flex),防止换行破坏滚动逻辑 - 滚动条美化可选:Chrome/Edge 支持
::-webkit-scrollbar,Firefox 需 JS 模拟 - 真机测试重点:iOS Safari 对
overflow-x: auto的 touch 惯性支持较弱,需加-webkit-overflow-scrolling: touch
IE11 兼容双排 flex 布局的补丁细节
IE11 支持 display: -ms-flexbox,但不支持 flex-wrap: wrap 的某些组合行为,尤其在子项含 min-width 时容易撑破容器。
绕过方式不是降级回 float(已不可维护),而是微调声明顺序和 fallback:
- 同时写两套声明:
display: -ms-flexbox; display: flex;,-ms-flex-wrap: wrap; flex-wrap: wrap; - 避免用
flex: 1,改用-ms-flex: 1; flex: 1;,否则 IE11 可能忽略换行 - 若内容超长,
word-break: break-all比white-space: nowrap更稳妥(后者在 IE11 中可能失效) - 不要依赖
gap,IE11 不支持,用margin-right+:last-child清除
双排菜单最难的不是“怎么排成两行”,而是“折行后 hover 仍准确定位 + 小屏不崩溃 + 老浏览器不飘”。这三个条件缺一不可,漏掉任意一个,用户就会在某个设备上看到菜单飞走或点不开。



















