在网页排版中,我们经常遇到这样一种需求:有一批宽度相近的块级元素,比如商品卡片、图标按钮或者标签,希望它们在容器中根据可用宽度自动决定列数,并且排列顺序是从上到下先填满第一列,再填第二列,也就是所谓先列后行。很多人习惯用 Flexbox 去做,但 Flex 的默认主轴是水平方向,排出来的是先从左往右换行,不符合先列后行的直觉。CSS Grid 虽然默认也是按行填充,但通过几个关键属性就能轻松翻转填充逻辑。

理解 Grid 的轨道与自动放置机制
CSS Grid 布局的核心在于把容器划分成若干行轨道和列轨道。当我们只声明了 grid-template-columns 而没有写 grid-template-rows 时,行轨道会由内容自动生成,这叫做隐式网格。网格里的子项默认按照 grid-auto-flow 指定的方向依次寻找空位放置,初始值是 row,意思是先从左到右填一行,满了再换到下一行,这就是典型的先行后列。
要实现先列后行,本质就是改变自动放置的流向。规范里 grid-auto-flow 除了 row 还可以取 column,它会让子项优先向下填满当前列,再移向相邻的列。但这里有个坑:如果列轨道数量是固定的,比如写了 grid-template-columns: repeat(3, 1fr),那么用 column 流向时,元素会先填完前三行的第一列才去第二列,看起来就像三列被拉成了长条。因此真正实用的先列后行自适应,往往要结合自动列数来用。
另外要注意,隐式生成的行或列尺寸由 grid-auto-rows 和 grid-auto-columns 控制。在 column 流向模式下,自动新增的是列轨道,所以应当用 grid-auto-columns 来约束每列宽度,否则列宽可能塌缩成内容宽度,破坏整体节奏。
用 auto-fill 与 minmax 构建自适应列
单纯设置 grid-auto-flow: column 并不能让列数随屏幕变化,因为我们仍需告诉浏览器列轨道怎么产生。最佳实践是使用 grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))。其中 auto-fill 表示根据容器宽度尽可能多地创建 200px 以上、均分剩余空间的列;minmax 保证窄屏时列不会挤扁。此时再配合 grid-auto-flow: column,子项就会在自动算出的多列里优先向下排,形成先列后行且响应式的布局。
下面是一段可直接运行的示例。容器宽度改变时,列数会自动增减,而内部方块始终先填第一列再填第二列。注意 grid-auto-columns 在这里其实不需要额外写,因为列模板已经由 repeat(auto-fill, ...) 显式定义了,自动流只负责往里塞。如果未来想限制最多几列,可以把 auto-fill 改成具体数字。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<style>
.box {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
grid-auto-flow: column;
gap: 10px;
height: 300px;
}
.item {
background: #4caf50;
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 20px;
}
</style>
</head>
<body>
<div class="box">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
</div>
</body>
</html>
上面的代码给容器设了固定高度 300px,这是为了直观看到列填满后换列的效果。如果去掉高度,容器高度会被隐式行高撑开,此时 column 流向依然有效,但视觉上更像是普通网格。实际项目中,卡片流通常不限高度,那么先列后行更多体现在 DOM 顺序与视觉顺序一致,而非强制分块换列。
对比 Flexbox 与书写模式取巧方案
有些开发者会用 Flexbox 加 flex-direction: column 和固定容器高度来模拟先列后行,但这种方法必须提前知道高度才能算每列几个,无法纯靠宽度自适应。还有人借助 writing-mode: vertical-lr 把整个容器竖排,再在里面用横排子项,虽然能实现先列后行,但会带来文字方向、滚动条位置等副作用,维护成本高。
相比之下,Grid 的方案语义清晰:列数自适应交给 repeat(auto-fill, minmax()),流向交给 grid-auto-flow: column,两者职责分离。下表列出三种方式差异。
| 方案 | 是否宽度自适应 | 是否先列后行 | 额外成本 |
|---|---|---|---|
| Flex 横排换行 | 是 | 否 | 无 |
| Flex 竖排加高度 | 否 | 是 | 需 JS 算高度 |
| Grid auto-fill + column | 是 | 是 | 几乎无 |
从表格可以看出,Grid 组合拳在自适应和流向控制上都是最优解。若遇到旧浏览器兼容问题,可以考虑用 @supports 检测 display: grid 不支持时回退到 Flex 横排,至少保证内容可读。现代项目里,直接采用 Grid 写法即可大幅简化布局逻辑,也不用再写一堆媒体查询去调列数。
调试技巧与常见误区
当你发现元素还是从左到右排列,第一反应是检查 grid-auto-flow 是不是被其他样式覆盖,比如某些重置 CSS 里写了 grid-auto-flow: row。浏览器开发者工具的布局面板能直接看到网格线和流向箭头,是排查首选。另一个误区是以为 grid-template-rows 也要设成 auto-fill,其实行在 column 流向里是隐式生成的,不需要显式重复。
还有人把 grid-auto-flow: column dense 拿来用,dense 会尝试回填前面空隙,在动态增删卡片时可能打乱视觉顺序,若只求先列后行普通 column 就够了。最后提醒,如果子项本身有 grid-row 或 grid-column 明确跨轨,自动放置算法会让位给显式位置,那时流向规则就不再完全生效,需要整体审视网格声明。
CSS_Gridgrid-template-columns自适应排列修改时间:2026-08-13 09:06:56