display: flex + flex-wrap: wrap 是最直接可控的换行方案,需将 ul 设为 flex 容器、li 设为弹性子项,用 flex-basis 配合 gap 和媒体查询实现响应式多列布局。

用 display: flex + flex-wrap: wrap 是最直接、最可控的方式,比 float 或纯 ul/li 默认流更可靠,也比 grid 更轻量——尤其当你只需要一维换行、不涉及行列对齐时。
为什么 ul 默认不自动换行?
ul 和 li 本身是块级元素,但默认行为是“垂直堆叠”,不是“水平排列后换行”。想让 li 横向排布并自动折行,必须显式改变其布局上下文:
-
li默认display: list-item,它不参与 flex 或 grid 容器的自动换行逻辑,除非你重设display - 只给
ul设width不起作用——li仍会各自占满一行,不会横向挤在一起 - 用
inline-block虽然能横排,但空格/换行符会产生不可控间隙,且换行后对齐难调
flex-wrap: wrap 配合 flex-basis 控制每行数量
核心是让 ul 成为 flex 容器,li 成为弹性子项。关键不在“是否换行”,而在“换行点怎么算”:
- 必须给
ul加display: flex和flex-wrap: wrap -
li推荐用flex: 0 0 calc(33.333% - 0.5rem)实现三列 ——flex-basis决定基础宽度,减去gap的一半避免溢出 - 别用
flex: 1,它会让所有li强制等宽撑满,小屏下可能单列都显示不全 - 用
gap: 0.5rem替代margin,避免父子 margin 折叠或重复计算
移动端适配:避免写死列数
硬编码 calc(25% - ...) 在手机上大概率导致文字挤成一团。响应式要点是“最小内容宽度优先”,不是“固定列数”:
立即学习“前端免费学习笔记(深入)”;
- 桌面端想要四列?用
flex-basis: calc(25% - 0.75rem) - 平板改三列?加媒体查询:
@media (max-width: 768px) { li { flex-basis: calc(33.333% - 0.5rem); } } - 手机屏直接单列?
@media (max-width: 480px) { li { flex-basis: 100%; } } - 更进一步:用
min-width: 280px配合flex-basis,确保单个li不会窄于可读宽度
常见翻车现场和修复
这些错误几乎每次重构都会出现一次:
-
ul上写了flex-wrap: wrap,但忘了删掉li的float: left—— float 会脱离文档流,flex 完全失效 - 给
li设了width: 25%,又在媒体查询里改width: 50%,结果 desktop 下四列、mobile 下两列,中间断层没过渡 - 用了
justify-content: space-between,但最后一行只有两个li,它们被拉到两端,中间大片空白 —— 改用flex-start更稳妥 - 列表含图标或 badge,绝对定位元素没包在
position: relative的li里,换行后飘到别的行上面
真正麻烦的从来不是“怎么让它换行”,而是“换行后每行高度是否一致”“文字截断是否自然”“点击热区是否完整”——这些细节得靠 min-height、overflow: hidden 和 line-clamp 组合补位,不能只靠布局属性一招鲜。



















