CSS Grid 网格布局速查表 - Grid 网格布局属性大全
Grid 与 Flexbox 的分界只有一条,但踩错的代价很大:只控制一根轴就用 Flex,需要行和列同时对齐就用 Grid。整页骨架——固定页眉、侧栏加内容区、仪表盘面板——天然是二维问题,硬用 Flex 嵌套三层去做列对列对齐,代码会迅速失控。轨道尺寸优先用 fr 与 minmax,而不是百分比:fr 让剩余空间按比例分配,minmax(200px, 1fr) 给每列设下限并保留弹性,配合 auto-fit 与 auto-fill 就能在不加媒体查询的情况下自适应。表里按容器定义、间距与对齐、网格单元与跨域、显式与隐式轨道、常用模式、响应式技巧分组,还包含 grid-template-areas 这种把布局画成字符串的写法——它牺牲一点灵活度,换来的是模板区域一眼可读、多人协作时不易错位。
典型使用场景
面向做整页布局而不是单个组件的工程师:后台仪表盘、卡片墙、图库、表单栅格、可切换侧边栏的主内容区。CSS Grid 真正的价值是让「父容器决定轨道、子项声明落点」这件事在 CSS 里表达出来,从而不必用嵌套的 float 或一堆 calc()。本表覆盖四组:容器定义(grid-template-columns/rows/areas、repeat)、间距与对齐(gap / justify-* / align-* / place-*)、单元跨域(grid-column / grid-row 的起止线与 span)、以及显式与隐式轨道(grid-auto-flow / grid-auto-rows / dense)。最容易踩的三个坑:auto-fill 与 auto-fit 的差别、隐式行的默认尺寸、以及 `1fr` 在 minmax 里不加 min 时内容撑破轨道。
容器定义 8
display: griddisplay: inline-gridgrid-template-columns: 1fr 2fr 1frgrid-template-rows: 100px auto 100pxgrid-template-columns: repeat(3, 1fr)grid-template-columns: repeat(auto-fill, minmax(200px, 1fr))grid-template-columns: repeat(auto-fit, minmax(200px, 1fr))grid-template-areas: "header header" "sidebar main" "footer footer"间距与对齐 10
gap: 16pxrow-gap: 16pxcolumn-gap: 16pxjustify-items: stretchjustify-items: centeralign-items: centerplace-items: centerjustify-content: centeralign-content: centerplace-content: center网格单元与跨域 7
grid-area: headergrid-area: 1 / 1 / 3 / 3grid-column: 1 / 3grid-row: 1 / span 2grid-column: 1 / -1grid-column: span 2grid-row: span 3显式与隐式轨道 6
grid-auto-columns: 100pxgrid-auto-rows: 100pxgrid-auto-flow: rowgrid-auto-flow: columngrid-auto-flow: densegrid-auto-flow: row dense常用模式 6
grid-template-columns: 1fr 1fr 1frgrid-template-columns: 200px 1frgrid-template-columns: repeat(12, 1fr)grid-template-columns: minmax(0, 1fr) minmax(0, 1fr)grid-template-areas: "header" "main" "footer"grid-column: 1 / -1响应式技巧 5
repeat(auto-fit, minmax(200px, 1fr))repeat(auto-fill, minmax(150px, 1fr))repeat(auto-fit, minmax(min(100%, 250px), 1fr))@media (max-width: 768px) { grid-template-columns: 1fr }grid-auto-rows: minmax(150px, auto)参数矩阵
| 参数 | 作用 | 示例 |
|---|---|---|
display: grid | 把容器变成网格格式化上下文,direct child 自动成为网格项 | display: grid |
display: inline-grid | 网格按行内块参与外层排版,宽度收缩到内容,适合嵌在文字流里的小控件 | display: inline-grid |
grid-template-columns: 1fr 2fr 1fr | 显式列轨道,fr 分配剩余空间;三列布局最常见的一行 | grid-template-columns: 1fr 2fr 1fr |
grid-template-rows: 100px auto 100px | 显式行轨道,auto 行由内容撑开;固定行与自适应行混排的经典写法 | grid-template-rows: 100px auto 100px |
grid-template-columns: repeat(3, 1fr) | 把一段轨道定义重复 N 次,避免手写长串 1fr | grid-template-columns: repeat(3, 1fr) |
repeat(auto-fill, minmax(200px, 1fr)) | 按容器宽度自动决定列数:空轨道也会被填充,所以容器变窄时最后一行项目左侧对齐 | grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) |
repeat(auto-fit, minmax(200px, 1fr)) | 同上但会折叠空轨道,容器变宽时项目被拉伸铺满,是响应式卡片墙的首选 | grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) |
grid-template-areas | 用字符串矩阵给区域命名,配合 grid-area 摆放,页头/侧栏/主体的经典三段式 | grid-template-areas: "header header" "sidebar main" "footer footer" |
gap / row-gap / column-gap | 轨道间距,取代 margin hack,且不会在容器边缘产生外边距 | gap: 16px |
justify-items / align-items | 控制网格项在其轨道内的对齐:justify 沿行内轴,align 沿块轴 | align-items: center |
justify-content / align-content | 控制整组轨道在容器内的分布,项数少于轨道数时才有效果 | justify-content: center |
place-items / place-content | align 与 justify 的简写,一次设两个轴 | place-items: center |
grid-area: 1 / 1 / 3 / 3 | 用起止线一次声明跨行跨列,顺序是 行起 / 列起 / 行止 / 列止 | grid-area: 1 / 1 / 3 / 3 |
grid-column: 1 / 3 | 显式跨列;写成 1 / -1 表示从第一列贯穿到最后,是通栏的常用写法 | grid-column: 1 / -1 |
grid-row: 1 / span 2 | 从第 1 行起跨 2 行,span 写法不依赖总行数,改版时更稳 | grid-row: 1 / span 2 |
grid-column: span 2 | 只声明跨度不给起点,由自动放置算法决定落在哪,是自适应磁贴布局的关键 | grid-column: span 2 |
grid-auto-rows: 100px | 设定隐式行的高度;不加时隐式行由内容决定,卡片高度容易参差 | grid-auto-rows: 100px |
grid-auto-columns: 100px | 设定隐式列的宽度,横向滚动容器里常用 | grid-auto-columns: 100px |
grid-auto-flow: row / column | 决定自动放置方向,row 是逐行填充,column 是逐列填充 | grid-auto-flow: column |
grid-auto-flow: dense | 回填空洞:小项能塞进前面留下的空位,代价是视觉顺序与 DOM 顺序脱节 | grid-auto-flow: dense |
grid-template-columns: 200px 1fr | 固定侧栏 + 弹性主内容,后台管理页最常用的一行 | grid-template-columns: 200px 1fr |
grid-template-columns: repeat(12, 1fr) | 12 列栅格,用 grid-column: span N 做按比例分栏,比手写百分比可靠 | grid-template-columns: repeat(12, 1fr) |
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) | 把 fr 的最小值钉成 0,等价于允许收缩,避免长内容把轨道撑破 | grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) |
repeat(auto-fit, minmax(min(100%, 250px), 1fr)) | min(100%, 250px) 保证窄屏下单列不会被 250px 的最小值撑出横向滚动 | grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr)) |
@media (max-width: 768px) { grid-template-columns: 1fr } | 断点处从多列塌成单列,是 Grid 响应式最省事的落点 | @media (max-width: 768px) { grid-template-columns: 1fr } |
grid-auto-rows: minmax(150px, auto) | 隐式行给一个最小高度并允许内容撑高,磁贴墙两边都照顾到 | grid-auto-rows: minmax(150px, auto) |
易错点与避坑指南
现象auto-fill 与 auto-fit 看起来一样,但最后一行项目没有铺满整行。
原因auto-fill 保留空轨道(1fr 仍分到空间),auto-fit 才折叠空轨道把空间让给已有轨道。
处置需要铺满用 auto-fit,需要保持对齐(背景条纹、序号列)用 auto-fill。
现象窄屏下页面出现横向滚动条,内容被裁掉一半。
原因minmax(200px, 1fr) 的 200px 是硬下限,视口小于 200px 时轨道仍保持 200px。
处置下限写成 min(100%, 200px),或在断点处把 grid-template-columns 改成 1fr。
现象某一列被一段很长的 URL 或代码块撑得特别宽,其它列被挤扁。
原因fr 的下限其实是 auto,即内容最小尺寸;长单词或 nowrap 会把轨道顶开。
处置给内容加 overflow-wrap: anywhere,或把轨道写成 minmax(0, 1fr) 从根上允许收缩。
现象子项设了 grid-column: 1 / 3 却没跨到预期位置,元素出现在下一行。
原因grid-area 与 grid-column/grid-row 的四个值顺序是 行起/列起/行止/列止,与书写直觉相反。
处置逐值确认行列次序,或改用更不易错的 grid-column 与 grid-row 分别声明。
现象项目高度参差不齐,卡片底部对不齐。
原因隐式行高度由内容决定,行高不一致;只设了 align-items 而没管行轨道。
处置用 grid-auto-rows: minmax(150px, auto) 给隐式行统一下限,或改用显式行模板。
现象加了 dense 之后 tab 顺序 / 朗读顺序与视觉顺序不一致。
原因dense 会让后面的项目被回填到前面的空位,DOM 顺序与视觉位置脱节。
处置依赖焦点顺序与读屏顺序时不要用 dense,改用显式 grid-column 指定每个磁贴位置。
现象grid-template-areas 布局在某处突然塌成一列。
原因areas 字符串里的空格与换行必须严格对齐行列,某一行的字符串数量少于其它行就会导致该行非法。
处置保证每行 areas 的 token 数一致、同一区域名构成矩形,必要时用 minmax(0, 1fr) 兜底。
现象嵌套 grid 时内层网格的 gap 与外层叠加,实际间距是两倍。
原因gap 不是可继承的 margin,父子都设了 gap 就会各自生效。
处置明确哪一层负责间距(通常外层),内层只设 padding。
排障路径
1确认容器确实成为网格格式化上下文
grep -n "display: grid" -r srcdisplay 写在了子项而不是容器上是无效的。
2把 areas 定义与 grid-area 命名对照检查
grep -n "grid-template-areas\|grid-area" -r src命名拼写不一致时该区域会被当作未命名的普通网格项处理。
3找出引入横向滚动的元素
grep -n "minmax(" -r srcminmax 的下限大于视口宽度是最常见的溢出源。
4排查 dense 是否破坏了焦点顺序
grep -n "dense" -r src有 dense 就需要确认 DOM 顺序与视觉顺序一致。
5统一检查断点处的塌列规则
grep -n "max-width: 768px" -r src确认每个多列容器都有对应的单列覆盖。
6核对隐式行是否都已设定高度
grep -n "grid-auto-rows" -r src缺它时行高由内容决定,是卡片墙高度参差的根源。
命令示例
命名区域做整体布局
.layout {
display: grid;
grid-template-areas:
"header header"
"sidebar main"
"footer footer";
grid-template-columns: 200px 1fr;
gap: 16px;
}
.header { grid-area: header; }
.sidebar { grid-area: sidebar; }
.main { grid-area: main; }
.footer { grid-area: footer; }命名区域的价值是「布局定义和子元素归属分离」:父级一处声明结构,子级只报名字,HTML 顺序乱了视觉也不会错位,特别适合响应式——小屏把模板改成单列再给每个区域一条 grid-area 即可,不用改任何子元素。
auto-fit 响应式卡片,无需媒体查询
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 16px;
}auto-fit 在容器变窄时自动减少列数,空轨道会折叠并把剩余空间分给已有列,所以卡片始终拉满宽度;auto-fill 则保留空轨道占位,行末有缺口。想要「最后一行不拉伸变形」就用 auto-fill。
minmax(0, 1fr) 修掉内容撑破轨道
.grid {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
}1fr 的实际下限是 auto,也就是轨道至少要装得下内容;长 URL 或 nowrap 文本会把轨道顶出容器,撑破布局。minmax(0, 1fr) 显式允许轨道收缩到 0,再由内部的 overflow 处理——两列网格溢出问题的标准解法。
用线定位做跨行跨列
.card {
grid-column: 1 / -1; /* 跨满整行 */
}
.wide {
grid-column: 1 / 3; /* 跨 2 列 */
}
.tall {
grid-row: 1 / span 3; /* 从第 1 行起跨 3 行 */
}线编号从 1 开始,-1 表示最后一条线。grid-column: 1 / -1 是「占满一行」最稳的写法,比 span N 更能适应列数变化——模板从 3 列改成 2 列时它依然横跨整行,而 span 3 会伸出网格。
隐式轨道与稠密填充
.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(150px, auto);
grid-auto-flow: row dense;
}子项多于显式列时会生成隐式轨道,默认高度由 grid-auto-rows 定死,容易把内容裁掉。用 minmax(150px, auto) 给一个高度下限、内容自适应高度。row dense 会让后面的项目回填前面的空位,视觉更整齐,但视觉顺序与 DOM 顺序不再一致——做无障碍焦点导航时要留意。
常见坑与注意事项
- fr 轨道的下限是 auto:长 URL、超长不换行文本或固定宽度图片会把轨道顶出容器,页面出现横向滚动条。两列以上布局统一用 minmax(0, 1fr) 替代 1fr。
- grid-template-areas 里的字符串必须构成矩形,且每行列数一致。少写一个格子会让整条规则被浏览器丢弃,布局静默塌成默认块级流——表现为「加了 areas 但完全没变化」。
- align-items / justify-items 作用于单元格内的项目,justify-content / align-content 作用于整个网格在容器中的位置,两组互不相干。想让网格整体居中却一直写了 justify-items: center,就是用错了属性。
- display: grid 后子项的 margin 不会撑开轨道尺寸,轨道按内容盒计算;再叠加大间距,很容易出现意外的空白列。间距统一交给 gap,不要靠 margin 撑布局。
- 老浏览器不支持 grid 时页面完全塌成单列流而非报错。仍需支持 IE 或旧 Android WebView 时用 @supports (display: grid) 包一层,提供 flex 降级。
- grid-auto-flow: dense 会打乱视觉顺序与 DOM 顺序的一致性,Tab 键焦点跳转会显得跳跃,屏幕阅读器读到的顺序也和看到的不一样。它只适合纯装饰的图集,且不应包含可聚焦的交互元素。
提示
- fr 是弹性单位,1fr 2fr 表示第二列是第一列的两倍宽。
- minmax(200px, 1fr) 表示最小 200px,最大弹性填充,配合 auto-fill 实现响应式。
- grid-template-areas 用可视化方式定义布局,代码可读性更好。
- gap 替代了旧的 grid-gap,是最新的标准写法。
- auto-fit 会折叠空轨道拉伸填满,auto-fill 保留空轨道,响应式布局常用 auto-fit。
- 隐式轨道由内容撑开且默认 auto 尺寸,想让溢出内容滚动需显式写 grid-template-rows: minmax(0, 1fr) 阻断撑开。
- grid-auto-flow: dense 会回填空洞让排版更紧凑,但视觉顺序会与 DOM 顺序不一致,慎用于可交互列表。
- 子项默认 stretch 会顶满轨道高度,需要保持内容高度时给该子项设 align-self: start。
常见问题
auto-fill 和 auto-fit 到底差在哪,响应式列该选哪个?
两者都用 repeat(auto-xxx, minmax(200px, 1fr)) 生成响应式列,区别在容器有剩余空间时怎么处理空轨道。auto-fill 会把空轨道保留下来占位,所以卡片数量少于列数时列宽不会拉伸,看起来左右留白;auto-fit 则把空轨道折叠掉,剩下的轨道一起分掉多余空间填满整行。做商品卡片这类「数量不定、希望铺满」的流式布局用 auto-fit,做需要保持统一列宽骨架的仪表盘列表用 auto-fill。
1fr 轨道里的内容老是撑破布局,该怎么修?
因为 1fr 的最小值默认是 auto,会被内容的最小尺寸撑大。把轨道写成 minmax(0, 1fr) minmax(0, 1fr) 就强制最小尺寸归零,轨道老老实实按比例分配,长内容改为溢出处理或换行。单列侧边栏加主内容也可以用 grid-template-columns: 200px 1fr,但要防主内容撑破,同样把 1fr 换成 minmax(0, 1fr)。
grid-template-areas 和手工写 grid-column 跨行,该选哪种?
看布局是否形状固定。页面骨架这种形状稳定、结构很少改的场景用 grid-template-areas: "header header" "sidebar main" "footer footer" 命名区域,再让子项写 grid-area: header,代码读起来就是一张图,好维护。内容位置多变、需要不规则排布的场景则直接用线定位:grid-area: 1 / 1 / 3 / 3 依次是行起、列起、行止、列止,grid-column: 1 / -1 表示横跨整行,grid-row: 1 / span 2 表示从第 1 线跨 2 行。
justify-items 和 justify-content 有什么不同?改一个没反应怎么办?
两者作用层级完全不同:justify-items 管的是每个网格单元内部子项怎么对齐,justify-content 管的是整条轨道在容器里怎么对齐。cell 内容没居中就改 justify-items: center 或 place-items: center;轨道整体没居中就改 justify-content: center 或 place-content: center。等价规则是先对齐轨道(content),再对齐单元内元素(items)。
小屏上自动列被内容挤成一条,怎么避免横向溢出?
两个手段一起用。第一,把 minmax 的下限换成 min() 兜底:repeat(auto-fit, minmax(min(100%, 250px), 1fr)),屏幕再窄轨道也不会超过容器宽度。第二,在窄屏断点直接降级为单列:@media (max-width: 768px) { grid-template-columns: 1fr },必要时把 grid-area 的命名区域也重排。行高则可以用 grid-auto-rows: minmax(150px, auto) 让行随内容自适应。
由 巧匠 维护
公开更新于 2026年7月21日,内容持续校对官方文档。