自动放置由grid-auto-flow决定流向而非逐格扫描:row按行填满再换行,column按列填满再换列,row dense允许回填缝隙但不改变dom顺序;手动定位项优先落位且不被覆盖。

自动放置从哪开始?先看 grid-auto-flow 的流向控制
Grid 自动放置不是从左上角“挨个格子扫”,而是由 grid-auto-flow 决定“推进节奏”:它定义的是“填满当前行(或列)再进下一行(或列)”,不是逐格线性遍历。
-
grid-auto-flow: row(默认):按行推进。第1行能放几个就放几个,放不下才换到第2行;即使第1行第3列空着,也不会把第4个元素塞进去 -
grid-auto-flow: column:按列推进。先填满第1列(从上到下),再填第2列,以此类推 -
grid-auto-flow: row dense:仍按行推进,但允许后续小尺寸项回头填前面因跨列(如grid-column: span 2)留下的缝隙
注意:dense 不改变 DOM 顺序,也不重排视觉流——它只影响“哪个空位被谁填”,对屏幕阅读器、Tab 键序、打印样式等无感知,容易造成语义断裂。
手动定位项如何影响自动项?三件事决定谁先落位
自动放置算法分阶段执行,**明确位置的项永远优先**,且不参与后续自动流计算。
- 带
grid-column、grid-row或grid-area的项,直接按坐标落位,其他元素绝不会挤占或覆盖它 - 多个手动项若重叠(比如都设了
grid-row: 1和grid-column: 1),后声明的 CSS 规则生效(层叠规则起作用) - 未定位项只在“剩余空白轨道”里找地方——它们不会拆掉已定位项来填空,也不会跳过显式定义的行列去占用隐式轨道
例如:.item-a { grid-column: 2 / 4; } 占据第2–3列,则自动项在第1行只会尝试第1列和第4列(如果存在),第2–3列区域被视作“已锁定”。
立即学习“前端免费学习笔记(深入)”;
空位没被填上?检查隐式轨道是否生成 & dense 是否真生效
你以为有空位,Grid 却没填——常见原因不是算法失效,而是你没给它“填的资格”。
- 没有显式定义足够列数(如
grid-template-columns: repeat(3, 1fr)),又没设grid-auto-columns,那么超出部分会生成隐式列,但宽度为auto(内容撑开),可能视觉上“看不见空位” -
row dense只对“尺寸刚好匹配缝隙”的后续项生效。比如第1行留了1格空位,但下一个自动项设置了grid-column: span 2,它依然会被推到下一行——dense 不缩放、不裁剪、不变形 - 浏览器 DevTools 的网格叠加层(Layout → Grid)必须打开,才能看清哪些是显式轨道、哪些是隐式生成的行列,否则你看到的“空”可能是隐式轨道未渲染或被内容撑高了
怎么调试自动放置行为?用最小可验证案例 + 浏览器工具
别靠猜,用可控变量逐步验证:
.debug-grid {
display: grid;
grid-template-columns: repeat(4, 100px);
grid-template-rows: repeat(3, 80px);
grid-gap: 4px;
grid-auto-rows: 80px;
grid-auto-flow: row dense;
}
.debug-grid > * {
background: #eef;
border: 1px solid #999;
}
.debug-grid > :nth-child(3) {
grid-column: span 2;
}
.debug-grid > :nth-child(7) {
grid-row: 2;
}这个例子中::nth-child(3) 占两列 → 第1行剩2格;:nth-child(7) 被手动拉到第2行 → 第1行那2格就成“可回填目标”。开启 DevTools 网格叠加,就能立刻看到 :nth-child(4) 是否真的填进了第1行第3列——而不是凭感觉判断。
最常被忽略的一点:自动放置算法不关心内容高度或溢出,只认轨道尺寸与跨度声明。哪怕一个 div 里塞了 10 行文字,只要它的 grid-row 没变,它就只占声明的那几行,多余内容会溢出或撑高隐式行——这和你是否开了 grid-auto-rows 直接相关。










