低版本 safari(≤14.1)存在三大语法断层:display: flex 被忽略,需写 display: -webkit-flex 并同步加前缀;gap 完全不支持,须用负 margin + 正 margin 模拟;flex: 1 错误解析为 flex-basis: auto 导致坍塌,须显式设 flex-basis: 0px 且配套 min-height: 0 或 min-width: 0。

低版本 Safari(≤14.1)对 Flex 布局的支持不是“差一点”,而是存在多个语法级断层——display: flex 被忽略、gap 完全不解析、flex: 1 解析为 flex-basis: auto 导致高度坍塌。靠 autoprefixer 自动补前缀或只加 @supports (gap: 0) 检测,大概率会让布局在 iOS 14.5 或 macOS Safari 12 上直接错位甚至塌陷。
为什么 display: flex 在 Safari 9–12 里等于没写
Safari 9–12 实现的是旧版 Flexbox 草案,根本不识别标准 display: flex。它只响应 display: -webkit-flex,且所有依赖属性必须同步加前缀:
-
flex-direction→-webkit-flex-direction -
justify-content→-webkit-justify-content -
align-items→-webkit-align-items -
flex-wrap→-webkit-flex-wrap -
flex简写 →-webkit-flex(注意不是-webkit-flex-box)
autoprefixer 只有在 browserslist 明确包含 ios_saf >= 9 或 safari >= 9 时才会输出这些前缀;写 last 2 versions 会直接跳过 Safari 12。
gap 属性在 Safari ≤14.1 中压根不存在
DevTools 里 gap 显示为灰色带删除线、getComputedStyle(el).gap 返回空字符串,就说明浏览器根本没解析它。这不是 bug,是规范未实现。
-
@supports (gap: 0)不可靠:Safari 14.1 会误判为支持,但实际仍跳过该声明 - 正确检测方式是双条件:
@supports (grid-row-gap: 0) and (row-gap: 0) - 降级方案必须用负 margin + 正 margin:容器设
margin-left: -8px; margin-right: -8px; overflow: hidden,子项设margin-left: 8px; margin-right: 8px - 每个子项必须加
min-width: 0和box-sizing: border-box,否则内容撑宽时会溢出或换行错乱 - 清除首项 margin 不能用
:not(:first-child)(旧 Safari 不支持),改用:nth-child(n+2)
flex: 1 在 Safari 9–12 中导致高度坍塌的真正原因
旧版 Safari 把 flex: 1 错误解析为 flex: 1 1 auto,而 flex-basis: auto 会触发默认 min-height: auto,结果就是子项拒绝拉伸、高度坍缩为 0。
- 必须显式写
flex-basis: 0px(不能写0%,Safari 会忽略) - 配套必须加
min-height: 0(垂直主轴)或min-width: 0(水平主轴) - 若子项含
<img>,额外加height: auto,否则 Safari 可能冻结其尺寸估算 -
flex-basis: 0px生效的前提是父容器有确定高度(如height: 100vh或固定定位),否则整个校准链失效
button 元素上直接设 display: flex 无效
在 iOS 8.4、Safari 9 之前等环境,<button></button> 是受限弹性容器,即使写了 display: flex,align-items 和 justify-content 也会被忽略。
- 不要在
<button></button>上直接设display: flex,改用内层<span></span>或<div> 包裹并设 <code>display: flex - 显式声明
box-sizing: border-box,否则各浏览器对按钮内边距计算不一致 -
flex: 1 0 0必须配合min-width: 0才能真正等宽;仅写flex: 1会被 Safari 的最小宽度策略覆盖 - 清除
<button></button>默认padding和border,避免挤压内层 flex 容器
真正容易被忽略的不是前缀本身,而是那些必须成对出现的防护性声明:overflow: hidden、min-width: 0、box-sizing: border-box —— 少一个,布局就在窄屏、缩放或换行时突然崩掉。











