<p>移动端九宫格不能直接用 width: 33.333% 因小数像素四舍五入导致间隙或换行;应使用 grid-template-columns: repeat(3, calc((100% - 2 * 4px) / 3)) 配合 gap: 4px 实现精确布局。</p>

九宫格在移动端为什么不能直接写 width: 33.333%
因为移动端屏幕宽度不固定,且存在小数像素四舍五入导致的间隙或换行。比如在 375px 屏上,33.333% × 375 ≈ 124.99875px,浏览器渲染时可能向下取整为 124px,三列加起来只剩 372px,留下 3px 空隙——这空隙会触发 flex 或 float 的换行逻辑,尤其在 iOS Safari 中更敏感。
用 calc() 可以把边框、间隙等变量显式剥离,让每项宽度真正“占满”容器:
grid-template-columns: repeat(3, calc((100% - 2 * 4px) / 3));
这里 4px 是两列之间的总 gap(即列间距),减去后再均分,避免累积误差。
grid-template-columns 配合 gap 的正确写法
别用 margin 模拟间隔——它会干扰 grid 自动对齐;也别用 padding + box-sizing: border-box 来硬挤,那样内容区域不可控。
立即学习“前端免费学习笔记(深入)”;
- 用
gap: 4px统一控制行列间距,语义清晰,且不会影响子项尺寸计算 -
grid-template-columns只负责列宽,不包含 gap:写成repeat(3, 1fr)最简洁,但需配合gap才能实现视觉九宫格 - 若要固定宽高比(如正方形格子),子项用
aspect-ratio: 1 / 1,而不是靠padding-top做 hack - 旧版 Android(
Chrome )不支持 <code>aspect-ratio,此时 fallback 方案是:height: 0; padding-top: 100%+position: relative+ 内容绝对定位
calc() 里混用单位时的常见翻车点
calc() 不允许单位不一致的运算,比如 calc(100% - 10px) 合法,但 calc(100vw - 1rem) 在部分安卓 WebView 中会失效——不是语法错,而是 rem 基准未就绪时计算值为 NaN。
- 优先用
px或%做 gap 和边框,避免混用rem/em与视口单位 - 如果必须响应式 gap(比如大屏加大间距),改用媒体查询单独设
gap,别塞进calc() -
calc()里的空格不能省:calc(100%-4px)是无效的,必须写成calc(100% - 4px) - 在
@container查询中慎用calc(),目前支持度低,容易退化为 0
兼容性兜底:当 display: grid 不可用时
iOS 9.3 和 Android 4.4 的原生浏览器不支持 grid,但它们支持 flex 和 calc()。此时可降级为三列 flex:
.grid-fallback {
display: flex;
flex-wrap: wrap;
}
.grid-fallback > * {
width: calc((100% - 2 * 4px) / 3);
margin-right: 4px;
margin-bottom: 4px;
}
.grid-fallback > *:nth-child(3n) {
margin-right: 0;
}注意:这个方案需手动处理最后一行右间距,且无法自动换行对齐(flex 每行元素数不固定),所以只作为最后手段。真要保老系统,建议用 JS 检测 CSS.supports('display', 'grid') 动态加类。
最易被忽略的是:gap 在 flex 中无原生支持,所有“间隙”都得靠 margin 实现,而 margin 会参与盒模型计算——这意味着你必须确保子项没设置 box-sizing: border-box,否则宽度会少算边框,导致错位。


















