先记住这个答案
grid-auto-flow 控制没有明确位置的项目怎样进入网格。默认 row 按行推进;column 按列推进。若一个跨两列的大卡片塞不进当前行,稀疏模式会跳到后面,留下空格;加 dense 后,后续较小卡片可能回到前面的空格。它只负责摆放顺序,不会改变项目在文档里的先后。
row默认沿行推进column改为沿列推进dense会尝试回填空格- 回填可能打乱视觉阅读顺序
为什么会留下空格
假设容器有三列,第一张卡片占两列,第二张也占两列。第二张无法放进第一行剩下的一列,所以移到下一行,第一行尾部留下空格。默认自动放置游标继续向前走;即使第三张只占一列,也通常不会回填那个洞。
.gallery {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
grid-auto-flow: row dense;
gap: 12px;
}
.gallery .wide { grid-column: span 2; }
/* 后来的窄卡片可能回填早先空出的单列 */dense 会重新寻找较早的可用位置,却不能保证消除所有空白。项目跨度、显式定位和可用轨道都限制它。它也不是瀑布流算法:普通 Grid 的同一行仍共享行高,卡片高度不同留下的纵向空隙不会自动像瀑布流那样填满。
列方向与顺序风险
column 的自动放置游标优先沿列推进,适合已给定行数、希望先填满第一列再去下一列的布局。若没有合适的显式行,浏览器还会按需要建立隐式轨道;不要仅凭 column 一词猜最终有多少列。
商品列表或文章目录通常要求视觉顺序、键盘导航和读屏顺序一致。dense 可能把后面的项目移到视觉上的前面,但 Tab 仍按 DOM 顺序走。用户眼睛看到第三张,焦点却从第二张跳到更靠后的格子,这种界面应避免密集回填。
可以手算三列例子:第一张宽卡占第 1、2 列,第二张宽卡只好到下一行,第 1 行第 3 列留下洞。默认稀疏模式中,第三张窄卡接在第二张后面;row dense 则可把它放回第一行第 3 列。这样“第三张”视觉上可能出现在“第二张”上方,但读屏仍先读第二张。dense 只是寻找可用网格单元,不会重新排列数据,也不能按卡片高度寻找最短列。
dense 对内容排序敏感:新增或删除前面的卡片,后续项目可能重新填入不同的空位。布局虽然更紧凑,视觉位置却可能跳动。图片墙若只是展示内容,这或许能接受;带编号步骤、价格顺序或可键盘操作的目录,就要优先保持视觉和文档顺序一致。
容易答错的地方
- 认为
dense会改 DOM 顺序 - 它只在布局阶段回填格子,不会重新排列节点。复制文本、辅助技术和键盘导航仍受文档顺序影响。
- 以为
column一定是竖排三列 - 它定义优先扫描方向,实际列数还依赖显式行、项目跨度以及隐式轨道的生成。
面试官还会怎么问?
什么时候不建议用 dense?
项目有明确阅读顺序、序号或键盘操作流程时,回填会让视觉位置与交互顺序脱节。
显式定位的项目也受 grid-auto-flow 控制吗?
已确定位置的项目优先按自己的线或区域放置;自动放置规则主要处理仍有未指定轴的项目。
row dense 能做真正瀑布流吗?
不能。普通 Grid 的行轨仍按整行内容定高,dense 只填网格单元的洞。
参考资料
示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。