跳到主要内容

Grid 布局

📐 CSS Grid 是面向二维行列结构的布局模型。下方子页面按“基础 → 属性 → 兼容性 → 注意事项”组织。

共同参考

Grid 布局:基础概念与使用方法

什么是 Grid 布局

CSS Grid 是二维布局系统,可同时控制行与列。适合页面级骨架、卡片宫格、 holygrail、仪表盘等「行列都要对齐」的场景。

核心术语:

  • Grid 容器display: grid / inline-grid
  • Grid 项目:容器的直接子元素
  • 网格线(grid line):划分轨道的线,从 1 开始编号
  • 轨道(track):两条相邻线之间的行或列
  • 单元格(cell):行列交叉的最小单位
  • 区域(area):一个或多个单元格组成的矩形
  • 间隙(gap):轨道之间的间距

如何启用

.container {
display: grid;
/* 或 */
display: inline-grid;
}

启用后,直接子元素成为网格项目;默认生成「单列多行」(每项占一行),需用模板属性定义多列。

最小可用示例

.gallery {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 16px;
}

三列等宽,间距 16px;项目按源顺序自动填充。

与 Flex 的直觉对比

FlexGrid
维度一维(行或列)二维(行和列)
内容驱动 vs 布局驱动更偏内容流更偏预设轨道
典型用途组件内对齐、导航页面骨架、宫格
重叠/跨格较弱天然支持跨行跨列

二者常组合:外层 Grid 搭骨架,内层 Flex 做对齐。

定义网格的两种思路

1. 显式轨道

.layout {
display: grid;
grid-template-columns: 200px 1fr 1fr;
grid-template-rows: auto 1fr auto;
gap: 24px;
min-height: 100vh;
}

2. 命名区域(可读性极强)

.layout {
display: grid;
grid-template-areas:
"header header header"
"nav main aside"
"footer footer footer";
grid-template-columns: 200px 1fr 240px;
grid-template-rows: auto 1fr auto;
}
.header { grid-area: header; }
.nav { grid-area: nav; }
.main { grid-area: main; }
.aside { grid-area: aside; }
.footer { grid-area: footer; }

自动放置 vs 手动放置

  • 自动:不写定位,按 grid-auto-flow 填充
  • 手动grid-column / grid-row / grid-area 指定占位
.featured {
grid-column: 1 / 3; /* 从第 1 条竖线到第 3 条 */
grid-row: 1 / 2;
}

fr 单位与 minmax

  • 1fr:分配剩余空间的一份弹性单位
  • minmax(min, max):轨道尺寸夹在最小最大之间
.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 16px;
}

这是响应式卡片宫格的经典写法,无需手写大量断点。

适用场景

  • 整页布局(头/侧/主/脚)
  • 卡片墙、图片墙、产品列表
  • 表单多列表格化排列
  • 仪表盘 modular 区块
  • 需要元素跨行跨列或对齐到同一网格线

学习路径

  1. grid-template-columns/rows + gap
  2. repeat / fr / minmax / auto-fit
  3. 线号定位与 grid-area
  4. 对齐属性 justify/align-items/content
  5. 隐式网格与 grid-auto-*
  6. 兼容性与注意事项

相关条目:容器属性、项目属性、兼容性、注意事项、与 Flex 选型对比。

Grid 容器属性详解

容器属性地图

类别属性
模板grid-template-columns / rows / areas
简写grid-templategrid
间隙gap / row-gap / column-gap
隐式网格grid-auto-columns / rows / flow
对齐justify-items / align-items / place-items
轨道整体justify-content / align-content / place-content

grid-template-columns / rows

定义显式列/行轨道。

.container {
display: grid;
grid-template-columns: 200px 1fr 2fr;
grid-template-rows: auto 1fr auto;
}

常用轨道尺寸

写法含义
px / rem / %固定或相对长度
fr剩余空间弹性份数
auto由内容/最大内容等决定
min-content / max-content内容最小/最大理想尺寸
minmax(a, b)夹在 a~b
fit-content(200px)类似 min(max-content, max(min-content, 200px))
repeat(n, …)重复轨道定义

repeat 与响应式

/* 固定 4 列 */
grid-template-columns: repeat(4, 1fr);

/* 自动填满:列宽至少 240px,能放几列放几列 */
grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));

/* 自动适配:必要时拉伸列以吃掉尾部空轨 */
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  • auto-fill:即使后面是空的,也尽量保留「可能的空列」结构
  • auto-fit:空列会被折叠,已有列可伸展填满

多数卡片墙用 auto-fit + minmax 更直观。


grid-template-areas

用名字画结构,必须构成矩形区域。

.page {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: auto 1fr auto;
grid-template-areas:
"sidebar header"
"sidebar main"
"sidebar footer";
gap: 0;
min-height: 100vh;
}
.sidebar { grid-area: sidebar; }
.header { grid-area: header; }
.main { grid-area: main; }
.footer { grid-area: footer; }
  • . 表示空单元格
  • 同一名字必须形成矩形,不能 L 形

媒体查询里可直接重排 areas,非常适合响应式骨架。

@media (max-width: 768px) {
.page {
grid-template-columns: 1fr;
grid-template-areas:
"header"
"main"
"sidebar"
"footer";
}
}

gap

.container {
gap: 16px;
/* row-gap column-gap */
gap: 12px 24px;
}

gap 不增加边缘外边距;比用 margin 模拟轨道间距更干净。Grid 的 gap 支持早于 Flex,兼容性通常更好(见兼容性篇)。


隐式网格

项目超出显式轨道时,会创建隐式行/列。

.container {
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(100px, auto);
grid-auto-flow: row; /* 默认按行填充 */
}
grid-auto-flow行为
row逐行放(默认)
column逐列放
row dense / column dense尽量回填空洞

dense 可能打乱视觉源顺序,注意无障碍。


对齐:items vs content

项目在单元格内(items)

.container {
justify-items: stretch; /* 水平,默认 stretch */
align-items: stretch; /* 垂直,默认 stretch */
place-items: center; /* align + justify 简写 */
}

常用值:start | end | center | stretch

整个网格在容器内(content)

当网格总尺寸小于容器时:

.container {
justify-content: center;
align-content: start;
place-content: start center;
}

取值类似 Flex 的 content 分布:space-betweenspace-around 等。


命名网格线

.container {
grid-template-columns: [full-start] 1fr [main-start] 640px [main-end] 1fr [full-end];
}
.item {
grid-column: main-start / main-end;
}

便于与设计系统的「内容最大宽 + 全宽通栏」模式配合。


实用模式

圣杯 / 后台框架

.app {
display: grid;
grid-template-columns: 240px 1fr;
grid-template-rows: 56px 1fr;
grid-template-areas:
"nav top"
"nav body";
height: 100vh;
}

响应式卡片

.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 260px), 1fr));
gap: 1rem;
}

min(100%, 260px) 可避免小屏下 minmax 最小轨道导致溢出。

十二栏系统(简化)

.grid-12 {
display: grid;
grid-template-columns: repeat(12, 1fr);
gap: 16px;
}
.span-6 { grid-column: span 6; }
.span-4 { grid-column: span 4; }

速记

  1. 先定轨道:template-columns/rowsareas
  2. 再定缝:gap
  3. 溢出轨道靠 auto-rows/columns + auto-flow
  4. 单元格内对齐用 *-items,网格在容器内对齐用 *-content

Grid 项目属性详解

项目属性总览

写在 Grid 项目上:

属性作用
grid-column-start / end列起止网格线
grid-row-start / end行起止网格线
grid-column / grid-row上述简写
grid-area区域名或四线简写
justify-self / align-self单元格内单项对齐
place-selfalign + justify 简写
order自动放置时的顺序权重

线号定位

网格线从 1 开始。N 列有 N+1 条竖线。

.item {
grid-column-start: 1;
grid-column-end: 3; /* 不包含第 3 条线之后的轨道,实际跨 2 列 */
grid-row: 2 / 4; /* 跨 2 行 */
}

简写形式

/* start / end */
grid-column: 1 / 3;
grid-row: 2 / span 2;

/* 只写起点,默认跨 1 轨 */
grid-column: 2;

/* span */
grid-column: span 2;
grid-column: 1 / span 3;

负数线号

-1 表示最后一条线,适合「贴右/贴底」:

.full-bleed {
grid-column: 1 / -1; /* 横跨所有显式列 */
}

grid-area

1. 使用 template areas 名称

.header { grid-area: header; }

2. 四值线号简写

/* row-start / column-start / row-end / column-end */
.item {
grid-area: 1 / 2 / 3 / 4;
}

可读性通常不如具名 area,复杂页面优先 grid-template-areas


跨列跨行实战

.gallery {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-auto-rows: 120px;
gap: 12px;
}
.gallery__hero {
grid-column: span 2;
grid-row: span 2;
}

注意:跨轨后,后续自动放置可能产生「空洞」;可用 grid-auto-flow: dense 回填(会改变视觉顺序)。


单元格内对齐

默认项目 stretch 拉满单元格。

.icon-cell {
justify-self: center;
align-self: center;
/* 等价 */
place-self: center;
}

.toolbar-item {
place-self: end stretch; /* 垂直 end,水平 stretch */
}

取值:start | end | center | stretch 等。

若项目有固有宽高或 max-width,stretch 可能看不出效果。


order

与 Flex 类似,影响自动放置顺序,不改 DOM / 无障碍顺序。

.item-late { order: 1; }
.item-first { order: -1; }

手动指定了线号的项目仍按其定位放置;order 主要影响参与自动布局的项。


与绝对定位

position: absolute 的子项通常不按网格自动占位(不占用网格单元格流),但若容器为定位包含块,仍可相对容器定位。需要「占格」请用 grid 定位而不是 absolute(除非要重叠装饰层)。

Grid 原生支持重叠:多个项目可以定位到同一区域,再用 z-index 控制层叠。

.card-media { grid-area: 1 / 1; }
.card-overlay { grid-area: 1 / 1; place-self: end; z-index: 1; }

子网格 subgrid(进阶)

.parent {
display: grid;
grid-template-columns: subgrid; /* 在子项上使用 */
}
.child {
display: grid;
grid-column: span 3;
grid-template-columns: subgrid;
}

subgrid 让子级对齐父级轨道,适合卡片内部多列与外层网格严格对齐。兼容性见《Grid 浏览器兼容性》。


常见组合片段

主内容限宽 + 偶发通栏

.page {
display: grid;
grid-template-columns: 1fr min(70ch, 100%) 1fr;
}
.page > * {
grid-column: 2;
}
.page > .breakout {
grid-column: 1 / -1;
}

表单两列表签

.form {
display: grid;
grid-template-columns: max-content 1fr;
gap: 12px 16px;
align-items: center;
}
.form .full {
grid-column: 1 / -1;
}

调试提示

  • DevTools 打开 Grid 徽章,查看线号与区域名
  • 混淆 start/end 时,记住 end 线是开区间边界
  • 跨度用 span 往往比硬算 end 线更稳

Grid 浏览器兼容性

总体结论(2024–2026 实务)

  • 标准 CSS Grid 在 Chrome / Edge / Firefox / Safari 及主流移动浏览器中已可作为默认布局方案
  • 无需再把 Grid 当成「渐进增强可选项」(除非明确要支持 IE 或极老 WebView)
  • 需单独评估的先进特性:subgridmasonry、部分新级联/容器查询组合

核心特性支持概况

特性ChromiumFirefoxSafariIE11
display: grid完整完整完整旧语法/部分
grid-template-*完整完整完整有限
gap(grid)完整完整完整不支持标准 gap
fr / minmax / repeat完整完整完整部分差异
命名 areas完整完整完整
auto-fit / auto-fill完整完整完整不可依赖
subgrid较新版本已支持支持较早16+ 等
masonry实验/有限有实现进展视版本

精确版本请以 Can I Use、MDN 与项目 browserslist 为准。工程上「Grid 基础」可视为基线能力。


IE10/IE11 历史包袱(遗留系统)

IE10/11 实现的是过时 Grid 语法,与现代标准不兼容,例如:

  • display: -ms-grid
  • -ms-grid-columns / -ms-grid-rows
  • 子项 -ms-grid-column

不建议手写双份布局去「完美支持 IE Grid」。可行策略:

  1. 产品放弃 IE,文档标明最低浏览器
  2. IE 降级为单列普通流 / 简单 float / block
  3. @supports (display: grid) 做增强
.layout {
/* 降级:单列 */
display: block;
}
@supports (display: grid) {
.layout {
display: grid;
grid-template-columns: 240px 1fr;
gap: 24px;
}
}

Autoprefixer 不能把标准 Grid 完整编译成 IE 旧 Grid。


gap 与旧前缀

  • 现代引擎:直接用 gap
  • 极老环境曾见 grid-gap 别名;新代码统一 gap
  • Grid 的 gap 普及早于 Flex gap,但仍应用目标浏览器验证

subgrid

用途:子级网格继承父级轨道对齐(卡片内部字段与邻卡齐线等)。

.card {
display: grid;
grid-template-rows: subgrid;
grid-row: span 3;
}

兼容策略:

  • 作为增强:无 subgrid 时卡片内部改用自有 grid/flex
  • @supports (grid-template-columns: subgrid) 分支
  • 不在最低支持面未覆盖时作为唯一实现路径

masonry(瀑布流)

原生 grid-template-rows: masonry 等仍处推进中,生产环境多数团队仍用:

  • 多列 + 绝对定位算法库
  • 或接受 CSS 多列 column-count 的阅读顺序限制
  • 或 Flex/Grid 近似方案

上线前确认目标浏览器是否正式支持,避免依赖实验旗标。


与容器查询、相对颜色等组合

Grid 常和以下特性一起用:

  • @container 做组件级响应式列数
  • min() / max() / clamp() 写轨道
  • :has() 调整列模板

这些要比「基础 Grid」更新,应单独列入兼容矩阵,而不是默认「能用 Grid 就能用全部」。

.cards {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: clamp(12px, 2vw, 24px);
}

min() 在现代浏览器广泛支持;若存在超老 WebView,需抽测。


推荐兼容策略

  1. browserslist 明确排除 IE(除非合同要求)
  2. 基础布局直接使用标准 Grid
  3. subgrid / masonry / 实验性值走 @supports 或 polyfill 替代方案
  4. 关键页面提供不依赖 Grid 的可读降级(单列堆叠通常足够)
  5. 用真机/云测覆盖:iOS Safari、Android Chrome、企业内常见内核

@supports 模板

.gallery > * {
margin-bottom: 1rem; /* 降级间距 */
}
@supports (display: grid) {
.gallery {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 1rem;
}
.gallery > * {
margin-bottom: 0;
}
}

测试清单

  • 显式多列在窄屏是否溢出(minmax + min(100%, …)
  • grid-template-areas 在断点切换后名称是否仍匹配
  • 隐式行高度与滚动容器
  • 跨列项目 + 自动放置空洞
  • 打印样式下网格是否可接受
  • 目标最低 iOS/Android 版本的 gap、fr、repeat

实务建议

Grid 基础能力当作现代前端默认技能栈;把兼容精力集中在业务声明的最低浏览器,以及 subgrid 等增强特性,而不是为 IE 维护第二套网格语法。

Grid 注意事项与常见坑

1. minmax 最小轨道在小屏溢出

现象repeat(auto-fit, minmax(300px, 1fr)) 在 320px 宽设备出现横向滚动。

原因:轨道最小 300px 大于容器。

解法

grid-template-columns: repeat(auto-fit, minmax(min(100%, 300px), 1fr));

2. 1fr 与最小内容尺寸

1fr 等价于 minmax(auto, 1fr) 的历史行为会影响「能不能比内容更窄」。长单词、大图可能撑破 fr 轨道。

.item { min-width: 0; } /* 或 overflow: hidden / auto */
/* 轨道侧 */
grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);

3. grid-template-areas 必须是矩形

同一区域名不能摆成 L / T 形,否则整段声明无效。

/* 无效示例概念:main 呈 L 形 */
/* 应拆成多个区域或改用线号定位 */

每行字符串代表一行,列数必须一致;用 . 占位空单元。


4. 隐式行高度失控

只定义了列、没定义行时,新增行走 grid-auto-rows(默认 auto)。等高卡片或虚拟滚动场景请显式:

grid-auto-rows: minmax(120px, auto);
/* 或 */
grid-auto-rows: 1fr; /* 需容器有明确高度才有「分份」意义 */

5. 百分比、fr 与 gap 混用的心智负担

gap 会从容器中先扣除再分 fr。用 % 列宽 + gap 时,总和可能超过 100% 导致溢出。优先 fr + gap,少用「多列百分比相加 = 100%」老套路。


6. 滚动只出现在某一网格区域

与 Flex 类似,需要:

.page {
height: 100vh;
display: grid;
grid-template-rows: auto 1fr;
}
.main {
min-height: 0; /* 关键 */
overflow: auto;
}

min-height: 0(或 minmax(0, 1fr) 轨道)时,1fr 行往往被内容撑开。


7. dense 打乱阅读顺序

grid-auto-flow: dense 会回填空洞,视觉顺序可能与 DOM/Tab 不一致。装饰性瀑布可接受;表单、文章、结账流程慎用。


8. 只有直接子元素是 grid 项

包装多一层就不再占据你定义的 area。用 display: contents 可让子级「穿透」成为网格项,但要注意无障碍与浏览器差异,慎用。


9. align/justify 名字易混

目标
所有项目在各自单元格内justify-items / align-items
单个项目justify-self / align-self
整个网格在容器内(有多余空间时)justify-content / align-content

Flex 里没有 *-items 对「单元格」这层,从 Flex 转 Grid 时最容易混。


10. 媒体查询与 areas 不同步

改了 grid-template-areas 却忘了改子项 grid-area 名称,或桌面 areas 有 aside、移动删除后未重置,会导致元素不显示或叠在错误位置。断点切换时做一次「名称对照表」。


11. 性能

  • 超大网格(成百上千格)+ 频繁变更模板成本高,列表虚拟化优先
  • 动画避免连续改 grid-template-columns 长字符串;可动画 transform 或用固定模板 + 改 span
  • DevTools 打开 Grid 调试层检查线号,避免盲调

12. 与 Flex 嵌套时的职责

反模式:外层 Flex 硬模拟二维对齐。更清晰的分工:

  • Grid:页面/区块二维结构
  • Flex:导航、按钮组、卡片脚注对齐

快速自检表

  • 小屏是否用了 min(100%, …) 保护 minmax
  • 可收缩轨道/项目是否 minmax(0, 1fr) / min-width: 0
  • areas 每行列数一致且为矩形
  • 滚动容器链上有 min-height: 0
  • 未在关键路径滥用 dense / order
  • gap 与百分比列未叠加溢出

稳妥默认

.stack-grid {
display: grid;
gap: 1rem;
}
.responsive-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
gap: 1rem;
}
.app-shell {
display: grid;
grid-template-rows: auto minmax(0, 1fr);
height: 100vh;
}
.app-shell > main {
overflow: auto;
min-height: 0;
}