<p>Flex布局无法直接控制每行数量,需通过width或min-width配合flex-wrap: wrap实现换行;“每行4个”本质是让卡片宽度为25%减去gap均摊值,如calc(25% - 12px),并注意IE11兼容性及等高、间距等细节处理。</p>

Flex布局无法直接控制“每行几个”,得靠width配合
Flex本身没有grid-template-columns那种显式列数控制能力。所谓“每行4个卡片”,本质是让每个卡片占容器宽度的1/4(减去gap),再用flex-wrap: wrap触发换行。浏览器不会数你放了几个子元素,只按实际宽度折行。
常见错误是只设flex: 0 0 25%却忽略gap带来的额外宽度,导致第4个卡片被挤到下一行——尤其在有gap或边框时更明显。
- 若容器宽400px、gap为16px,则4个卡片总间隙占3×16=48px,单个卡片可用宽度应为
(400 - 48) / 4 = 88px,而非100px - 更稳妥的做法:用
calc()动态扣除gap,例如flex: 0 0 calc(25% - 12px)(当gap: 16px时,左右gap均摊后每项需减12px) - 务必给父容器设
display: flex和flex-wrap: wrap,否则子项不会换行
用min-width + flex-wrap实现响应式“每行N个”
硬写25%在小屏上会变成超窄卡片。更实用的是按最小宽度定列数:比如“至少宽240px才放1个,宽480px放2个,720px放3个……”。这时不用百分比,改用min-width配合flex-basis。
示例:想实现“屏幕≥768px时每行3个”,可这样写:
立即学习“前端免费学习笔记(深入)”;
.cards {
display: flex;
flex-wrap: wrap;
gap: 16px;
}
.card {
flex: 1 1 0; /* 允许收缩,初始主轴尺寸为0 */
min-width: calc((100% - 32px) / 3); /* 减去2个gap,再除以3 */
}注意min-width里的计算必须和gap值严格对应;如果gap: 24px,那就要减48px(2个间隙)。
IE11兼容性下不要用gap,改用margin模拟
IE11不支持gap属性,用margin模拟时极易出现外边距叠加或首尾多出空白的问题。
- 避免直接给卡片设
margin-right和margin-bottom,会导致最后一行右侧多出空隙 - 推荐方案:用
:nth-child(3n)清除右margin(假设每行3个),并用:nth-last-child(-n+3)清除底部margin - 更稳的方式是包一层内边距容器:
.cards { padding: 0 8px; },卡片margin: 8px,靠负边距抵消首尾间隙 - Flex在IE11中对
flex-basis: 0解析不稳定,建议显式写flex-basis: 0%或具体像素值
卡片内容高度不一致时,用align-items: stretch还是flex-start?
默认align-items: stretch会让所有卡片拉伸到同一高度,看着整齐但可能撑大无关内容(比如文字少的卡片被迫留白)。而flex-start保持各自高度,但会导致行内顶部不对齐、视觉松散。
折中做法:
- 用
align-items: flex-start+row-gap(现代语法)或margin-bottom统一控制垂直间距 - 若必须等高,别依赖stretch——给卡片内部加
display: flex; flex-direction: column,再用margin-top: auto把按钮之类元素钉到底部 - 警惕
height: 100%在Flex子项中失效:它只对设了明确高度的父容器生效,而Flex容器高度常由内容决定
真正难的不是算宽度,而是当卡片里有图片、异步加载文字、动态展开区域时,如何让视觉节奏不崩。这时候百分比和calc都只是起点,往往得配合JS测高或CSS container queries做二次调整。


















