原生 gap 在旧版 Safari、IE、Android WebView 中不支持,需用 margin-left 或负 margin+padding 模拟;子项须设 flex-shrink: 0、min-width: 0 和 box-sizing: border-box;flex-wrap 下推荐 inline-block 或 JS 补齐。

原生 gap 在 Safari ≤14.1、iOS Safari ≤14.5、IE 全系、Android WebView @supports (gap: 0) 在 Safari 14.1 下会返回 true,但实际渲染错位,属于“伪支持”,不能信。
怎么快速确认 gap 是否真的生效
别靠猜,三步实锤:
- DevTools → Elements 面板选中 flex 容器,
gap值显示灰色或带删除线 - Computed 面板搜索
gap,值为空字符串''或标着not supported - 控制台执行
getComputedStyle(el).gap,返回''或'normal'
用 :nth-child(n+2) + margin-left 模拟水平 gap
这是兼容性最稳、无需 JS 的纯 CSS 方案,特别适合 iOS Safari 13.x / Android WebView 75 等“边缘旧环境”:
- 写法必须是
.flex-row > *:nth-child(n+2),不用:not(:first-child)(后者在 iOS 13.3 和 WebView 75 中失效) - 子项必须加
flex-shrink: 0,否则内容长时收缩,margin-left会“吃掉”文字或图标 - 间隙值统一走 CSS 自定义属性,如
--gap: 12px,后续改响应式只需调变量 - 若子项有
border或padding,margin-left值里要预留空间,否则视觉间隙不准
flex-wrap 场景下 margin 方案失效怎么办
水平 flex-wrap: wrap 时,margin-left 会导致换行后首项左侧多出一倍间隙——这不是 bug,是布局流自然结果。此时纯 CSS 很难精准清除每行末项,有两个更可靠的选择:
立即学习“前端免费学习笔记(深入)”;
- 改用
display: inline-block+font-size: 0消除空白符,再对子项设vertical-align: top和margin:兼容性极好,但失去justify-content、align-items等 Flex 对齐能力 - 轻量 JS 补齐:遍历容器子项,用
getBoundingClientRect()判断换行位置,在每行末尾后插入<div class="gap-filler"></div>,并监听resize - 如果项目已用 PostCSS,直接上
flex-gap-polyfill插件,构建时自动转成带calc()和 CSS 变量的兼容代码,零运行时开销
负 margin + padding 方案的硬性条件
手动模拟 gap: 16px 时,必须同时满足四点,否则在旧 Safari 里大概率出滚动条或布局塌陷:
- flex 容器加
overflow: hidden(否则负 margin 触发意外水平滚动) - 每个子项加
min-width: 0(默认min-width: auto,加padding后极易撑破容器) - 每个子项加
box-sizing: border-box(避免padding+border导致尺寸失控) - 间隙均分:容器设
margin-left: -8px; margin-right: -8px,子项设padding-left: 8px; padding-right: 8px
真正容易被忽略的是 min-width: 0 和 box-sizing: border-box ——它们不写,布局在旧 Safari 里就不是“差一点”,而是直接错位或溢出。


















