旧版 Safari(≤14.1)不支持 flex gap,需用负 margin + 正 margin 模拟,且必须加 overflow: hidden、min-width: 0、box-sizing: border-box 并均分间隙值。

旧版 Safari(≤14.1)压根不解析 gap,写了等于没写——这不是 bug,是规范未实现。直接上负 margin 方案最可靠,但漏掉 overflow: hidden 或 min-width: 0 就会出滚动条或布局塌陷。
怎么确认 gap 真的不被支持
别靠猜,用 DevTools 实锤:
- Elements 面板中选中 flex 容器,看
gap是否显示为灰色或带删除线 - Computed 面板搜
gap,值为空字符串''或normal就是未生效 - Console 执行
getComputedStyle(el).gap,返回空也说明浏览器不认识它
注意:Safari 14.1 是“伪支持”陷阱——@supports (gap: 0) 会返回 true,但实际在 flex 容器里仍跳过该声明。
用负 margin + 正 margin 模拟 gap 的硬性条件
核心是“容器外扩、子项内缩”,但 Safari ≤14.1 对 overflow 计算有 bug,必须满足以下四点才稳:
立即学习“前端免费学习笔记(深入)”;
规划您的迪拜之旅 — 哈利法塔观景、沙漠探险、迪拜购物中心购物、棕榈岛度假村及黄金市场砍价。还提供支持...
- Flex 容器加
overflow: hidden,否则负 margin 可能触发意外水平滚动条或截断右侧子项 - 每个子项加
min-width: 0,否则内容撑宽时破坏flex-shrink行为 - 每个子项加
box-sizing: border-box,避免padding+border导致尺寸失控 - 间隙值按半分:目标
gap: 16px→ 容器设margin-left: -8px; margin-right: -8px,子项设margin-left: 8px; margin-right: 8px
别用 :not(:first-child) 清首项 margin——旧版 Safari 和 Android WebView 不支持,改用 :nth-child(n+2)。
为什么不用 padding 替代 margin
用容器负 margin + 子项正 padding 看似更干净,但落地时三类问题高频出现:
-
flex-wrap: wrap下,换行后首项会多出顶部/左侧padding——得手动用:nth-child(3n+1)清除(假设每行 3 个) - 子项若有
border,padding+border易撑破容器宽度,必须配box-sizing: border-box - 子项设
display: none时,padding仍占位,视觉间隙错乱,需 JS 同步移除 class 或改用visibility: hidden+position: absolute
真正容易被忽略的是 min-width: 0——flex 子项默认不收缩,加上 padding 后极易溢出容器,尤其在响应式窄屏下。
要不要加 @supports 检测
多数项目没必要。原因很实在:
-
@supports (gap: 0)在 Safari 14.1 下误判为支持,降级逻辑被绕过,布局在换行时直接错位 - 更靠谱的检测是双条件:
@supports (grid-row-gap: 0) and (row-gap: 0),但维护成本高、体积大 - 如果项目明确支持 Safari 14.1+,就直接用原生
gap;否则全局走负 margin 方案,用 PostCSS 插件自动注入兼容代码更省心
最后提醒一句:所有方案都依赖子项是直系平级元素。HTML 中若存在换行符、空格或注释节点,会被解析为文本节点,导致布局错位——这不是 gap 的问题,得靠删空格、font-size: 0 或 display: contents 解决。

















