CSS Grid 布局(
display: grid
)是一种强大的二维布局系统,能够通过行和列的网格结构精确控制页面元素的排列。它能够将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局。
一、基本概念
1.容器与项目
通过设置 display: grid
或 display: inline-grid
的区域,称为”容器”(container)。其容器内部采用网格定位的子元素自动成为项目(Grid Item)。
<div>
<div><p>1</p></div>
<div><p>2</p></div>
<div><p>3</p></div>
</div>
上面代码中,最外层的 <div>
元素就是容器,内层的三个 <div>
元素就是项目。
注意:项目只能是容器的顶层子元素,不包含项目的子元素,比如上面代码的
<p>
元素就不是项目。Grid 布局只对项目生效。
2.行与列
容器里面的水平区域称为行(row
),垂直区域称为列(column
)。行和列之间的交叉区域,称为单元格(cell)。
上图中,水平的深色区域就是”行”,垂直的深色区域就是”列”。
正常情况下,n
行和 m
列会产生 n x m
个单元格。比如,3 行 3 列会产生 9 个单元格。
3.网格线与轨道
网格线:划分网格的线,称为”网格线”(grid line)。水平网格线划分出行,垂直网格线划分出列。划分行和列的虚拟线,通过编号或自定义名称引用(如 c1
, r2
)。
轨道:相邻网格线之间的区域,即行或列的宽度/高度。
二、容器属性
Grid 布局的属性分成两类。一类定义在容器上面,称为容器属性;另一类定义在项目上面,称为项目属性。
1.grid-template-columns 与 grid-template-rows
grid-template-columns
与 grid-template-rows
分别定义显式网格的列宽和行高,支持多种单位(如 px
、fr
、%
)和函数(如 repeat()
、minmax()
):
.container {
grid-template-columns: repeat(3, 1fr); /* 三列等宽 */
grid-template-rows: 100px auto minmax(200px, 1fr); /* 行高灵活 */
}
2.grid-template-areas
网格布局允许指定”区域”(area),一个区域由单个或多个单元格组成。
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-template-areas:
"a b c"
"d e f"
"g h i";
}
上面代码先划分出 9 个单元格,然后将其定名为a
到i
的九个区域,分别对应这九个单元格。
多个单元格合并成一个区域的写法如下。
grid-template-areas:
"a a a"
"b b b"
"c c c";
上面代码将 9 个单元格分成a
、b
、c
三个区域。
下面是一个布局实例。
grid-template-areas:
"header header header"
"sidebar main main"
"footer footer footer";
上面代码中,顶部是页眉区域header
,底部是页脚区域footer
,中间部分则为main
和sidebar
。
如果某些区域不需要利用,则使用”点”(.
)表示。
grid-template-areas:
"a . c"
"d . f"
"g . i";
上面代码中,中间一列为点,表示没有用到该单元格,或者该单元格不属于任何区域。
注意,区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为
区域名-start
,终止网格线自动命名为区域名-end
。比如,区域名为
header
,则起始位置的水平网格线和垂直网格线叫做header-start
,终止位置的水平网格线和垂直网格线叫做header-end
。
2.1 repeat()
有时候,重复写同样的值非常麻烦,尤其网格很多时。这时,可以使用repeat()
函数,简化重复的值。上面的代码用repeat()
改写如下。
.container {
display: grid;
grid-template-columns: repeat(3, 33.33%);
grid-template-rows: repeat(3, 33.33%);
}
repeat()
接受两个参数,第一个参数是重复的次数(上例是 3),第二个参数是所要重复的值。
repeat()
重复某种模式也是可以的。
grid-template-columns: repeat(2, 100px 20px 80px);
上面代码定义了 6 列,第一列和第四列的宽度为100px
,第二列和第五列为20px
,第三列和第六列为80px
。
2.2 fr
网格布局提供了fr
(fraction 的缩写,意为”片段”)来表示比例关系。如果两列的宽度分别为1fr
和2fr
,就表示后者是前者的两倍。
.container {
display: grid;
grid-template-columns: 1fr 2fr;
}
2.3 minmax()
minmax()
函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
上面代码中,minmax(100px, 1fr)
表示列宽不小于100px
,不大于1fr
。
2.4 auto
auto
表示由浏览器自己决定长度。
grid-template-columns: 100px auto 100px;
上面代码中,第二列的宽度,基本上等于该列单元格的最大宽度,除非单元格里的内容设置了min-width
,且这个值min-width
大于该列单元格的最大宽度。
2.5 auto-fill
有时,单元格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用auto-fill
表示自动填充。
.container {
display: grid;
grid-template-columns: repeat(auto-fill, 100px);
}
上面代码表示每列宽度100px
,然后自动填充,直到容器不能放置更多的列。
3.grid-auto-columns 与 grid-auto-rows
有时候,一些项目的指定位置,在现有网格的外部。比如网格只有 3 列,但是某一个项目指定在第 5 行。这时,浏览器会自动生成多余的网格,以便放置项目。
grid-auto-columns
属性和grid-auto-rows
属性用来设置,浏览器自动创建的多余网格的列宽和行高。它们的写法与grid-template-columns
和grid-template-rows
完全相同。如果不指定这两个属性,浏览器完全根据单元格内容的大小,决定新增网格的列宽和行高。
下面案例中,划分好的网格是 3 行 x 3 列,但是,8 号项目指定在第 4 行,9 号项目指定在第 5 行。
#container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-auto-rows: 50px;
}
.item {
font-size: 2em;
text-align: center;
border: 1px solid #e5e4e9;
}
.item-1 {
background-color: #ef342a;
}
.item-2 {
background-color: #f68f26;
}
.item-3 {
background-color: #4ba946;
}
.item-4 {
background-color: #0376c2;
}
.item-5 {
background-color: #c077af;
}
.item-6 {
background-color: #f8d29d;
}
.item-7 {
background-color: #b5a87f;
}
.item-8 {
background-color: #d0e4a9;
grid-row-start: 4;
grid-column-start: 2;
}
.item-9 {
background-color: #4dc7ec;
grid-row-start: 5;
grid-column-start: 3;
}
4.grid-gap
gap
:设置行间距和列间距(替代旧版 grid-gap
),简写形式为 gap: 行间距 列间距
:
.container {
gap: 10px 20px;
} /* 行距10px,列距20px */
5.grid-row-gap、grid-column-gap和grid-gap
grid-row-gap
属性设置行与行的间隔(行间距),grid-column-gap
属性设置列与列的间隔(列间距)。
grid-gap
属性是grid-column-gap
和grid-row-gap
的合并简写形式
grid-gap: <grid-row-gap> <grid-column-gap>;
如果
grid-gap
省略了第二个值,浏览器认为第二个值等于第一个值。
6. justify-items 与 justify-content
- 项目对齐:
justify-items
(水平)、align-items
(垂直),默认拉伸填充(stretch
)。 - 整体对齐:
justify-content
(水平整体位置)、align-content
(垂直整体位置),适用于网格总尺寸小于容器时。
该方法的使用和 Flex
弹性布局类似,此处不在过多赘述。
三、项目属性
1 grid-column-start、grid-column-end、grid-row-start、grid-row-end
项目的位置是可以指定的,具体方法就是指定项目的四个边框,分别定位在哪根网格线。
grid-column-start
属性:左边框所在的垂直网格线grid-column-end
属性:右边框所在的垂直网格线grid-row-start
属性:上边框所在的水平网格线grid-row-end
属性:下边框所在的水平网格线
.item-1 {
grid-column-start: 2;
grid-column-end: 4;
}
上述代码指:1 号项目的左边框是第二根垂直网格线,右边框是第四根垂直网格线。
2.grid-column 与 grid-row
grid-column
属性是grid-column-start
和grid-column-end
的合并简写形式,grid-row
属性是grid-row-start
属性和grid-row-end
的合并简写形式。
.item {
grid-column: 1 / 3; /* 跨越第1至第3列 */
grid-row: 2; /* 仅在第2行 */
}
.item-1 {
grid-column: 1 / 3;
grid-row: 1 / 2;
}
/* 等同于 */
.item-1 {
grid-column-start: 1;
grid-column-end: 3;
grid-row-start: 1;
grid-row-end: 2;
}
3.grid-area
grid-area
直接指定项目所属的命名区域(需配合 grid-template-areas
)。
#container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-template-areas:
"a b c"
"d e f"
"g h i";
}
.item {
font-size: 4em;
text-align: center;
border: 1px solid #e5e4e9;
}
.item-1 {
background-color: #ef342a;
grid-area: e;
}
.item-2 {
background-color: #f68f26;
}
.item-3 {
background-color: #4ba946;
}
.item-4 {
background-color: #0376c2;
}
.item-5 {
background-color: #c077af;
}
.item-6 {
background-color: #f8d29d;
}
.item-7 {
background-color: #b5a87f;
}
.item-8 {
background-color: #d0e4a9;
}
.item-9 {
background-color: #4dc7ec;
}
1 号项目位于e
区域,效果如下图。
grid-area
属性还可用作grid-row-start
、grid-column-start
、grid-row-end
、grid-column-end
的合并简写形式,直接指定项目的位置。
.item {
grid-area: <row-start> / <column-start> / <row-end> / <column-end>;
}
4.justify-self 与 align-self
justify-self
属性设置单元格内容的水平位置(左中右),跟 justify-items
属性的用法完全一致,但只作用于单个项目。
align-self
属性设置单元格内容的垂直位置(上中下),跟 align-items
属性的用法完全一致,也是只作用于单个项目。
.item {
justify-self: start | end | center | stretch;
align-self: start | end | center | stretch;
}
这两个属性都可以取下面四个值。
- start:对齐单元格的起始边缘。
- end:对齐单元格的结束边缘。
- center:单元格内部居中。
- stretch:拉伸,占满单元格的整个宽度(默认值)。
四、高级技巧与应用场景
1. 响应式布局
auto-fill
与 minmax()
结合:动态调整列数以适应容器宽度:
.container {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
2. 复杂布局示例
1.等分三栏布局
.container {
display: grid;
grid-template-columns: 1fr 2fr 1fr; /* 中间栏宽为两侧两倍 */
gap: 20px;
}
2.卡片网格
.container {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-auto-rows: 300px;
}
3.后台管理布局
.container {
display: grid;
grid-template-columns: 250px 1fr;
grid-template-rows: 100px 1fr 100px;
grid-template-areas:
"header header"
"aside main"
"aside footer";
height: 100vh;
}
.header {
grid-area: header;
background: red;
}
.aside {
grid-area: aside;
background: blue;
}
.main {
grid-area: main;
background: #f5f5f5;
}
.footer {
grid-area: footer;
background: yellow;
}
五、与 Flex 布局对比
特性 | Grid 布局 | Flex 布局 |
---|---|---|
维度 | 二维(行+列) | 一维(单行/列) |
适用场景 | 复杂网格结构(如仪表盘) | 线性排列(如导航栏) |
控制粒度 | 单元格级别 | 轴线级别 |
对齐方式 | 支持行列双向对齐 | 仅单轴对齐 |
六、兼容性与总结
- 兼容性:现代浏览器(Chrome、Firefox、Safari、Edge)均支持,IE 部分支持需前缀。
- 总结:Grid 布局通过行、列和区域的灵活定义,解决了传统布局难以实现的复杂结构问题,尤其适合响应式设计和多维内容排列。结合 Flex 布局,可覆盖绝大多数页面排版需求。
参考: