Grid 网格布局
Grid 用于二维布局,是 CSS 第一个真正意义上的布局系统。
.container {
/*
grid: 把容器当作 block 再按 grid 布局其项目。
inline-grid: 把容器当作 inline 再按 grid 布局其项目。
*/
display: grid | inline-grid;
}
2
3
4
5
6
7
<div class="container">
<div class="item item-1"> </div>
<div class="item item-2"> </div>
<div class="item item-3"> </div>
</div>
2
3
4
5
术语
grid line
网格线 line 的编号从 1 开始,和书写模式有关(rtl 时最右边的是 1)。
grid track
track 指两条 line 之间的空间。row track 就是 row line 间,column track 就是 column line 间的空间。
grid cell
单元格 cell 是最小单元,是行和列的交叉区域。
grid area
area 是一组 cell 在一起。
grid gap
gap 是 track 间的空隙。
容器属性
grid-template-columns,grid-template-rows
grid-template-rows:
定义网格的列、行。其值表示 track 的大小,分隔各值用的空格相当于 line 。包含:
- track 大小 – 可以为长度、百分比、fr 等
- 网格线命名 – 自动生成或用户指定的名字
网格线命名
网格线将从 1 开始被自动赋值(或从最后一条线开始从 -1 开始赋值)。
但也可以为网格线指定明确的名字:
.container {
grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];
grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line];
}
2
3
4
网格线可以同时有多个名字:
.container {
grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];
}
2
3
重名的网格线可以通过其名字和序号引用到:
.item {
grid-column-start: col-start 2;
}
2
3
grid-template-areas
依据 grid-area
所定义的区域名来定义整个网格的区域。可选值有三种:
- 与 grid-area 所对应的区域名
.
表示空的单元格none
表示区域未定义
示例:
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}
.container {
display: grid;
height: 200px;
grid-template-columns: 50px 1fr 50px 50px;
grid-template-rows: 40px auto 20px;
grid-template-areas:
"header header header header"
"main main . sidebar"
"footer footer footer footer";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<div class="container">
<div class="item-a">header</div>
<div class="item-b">main</div>
<div class="item-c">sidebar</div>
<div class="item-d">footer</div>
</div>
2
3
4
5
6
区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为 区域名-start
,终止网格线自动命名为 区域名-end
。正因此,某些网格线可能有多个名字,如上例最左侧网格线可用的命名为:header-start, main-start 及 footer-start
grid-template
grid-template-rows
grid-template-columns
grid-template-areas
的缩写形式。
综合使用示例:
.container {
grid-template:
[row1-start] "header header header" 25px [row1-end]
[row2-start] "footer footer footer" 25px [row2-end]
/ auto 50px auto;
}
/* 等价于:*/
.container {
grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
grid-template-areas:
"header header header"
"footer footer footer";
}
2
3
4
5
6
7
8
9
10
11
12
13
14
通常最好使用 grid
代替 grid-template
。
column-gap,row-gap
定义网格线的大小,可理解为行列间隙的宽度。
注:grid-column-gap
grid-row-gap
为废弃属性。
gap
row-gap
column-gap
的缩写形式。
注:grid-gap
为废弃属性。
justify-items
设置容器内所有 row 轴上的对齐方式。
align-items
设置容器内所有 column 轴上的对齐方式。
可以使用修饰符关键字:
safe
安全对齐方式会避免数据丢失的出现,将溢出转移到一边unsafe
不安全的对齐方式导致的对齐结果可能会发生数据丢失
align-items: safe end
place-items
align-items
justify-items
的缩写形式。
justify-content
用于网格整体内容的尺寸小于网格容器时,用来对齐整个网格在 row 轴上的内容。
align-content
用于网格整体内容的尺寸小于网格容器时,用来对齐整个网格在 column 轴上的内容。
place-content
align-content
justify-content
的缩写形式。
grid-auto-columns,grid-auto-rows
grid-auto-rows:
用来给自增的 track 设置尺寸。如上例中创建了两个区域:
.container {
grid-template-columns: 60px 60px;
grid-template-rows: 90px 90px;
}
.item-a {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.item-b {
grid-column: 5 / 6;
grid-row: 2 / 3;
}
2
3
4
5
6
7
8
9
10
11
12
区域 B 设置为 grid-column: 5 / 6
,但事实上并未定义这些网格线。由于引用了不存在的网格线,将会创建宽度为 0 的 track 来填补这些空隙。而 grid-auto-columns
正是用来定义这些 track 的宽度的。row 方向上同理。
grid-auto-flow
当网格中存在未明确指定位置的项目元素时,该属性用来指定其 自动摆放算法 采用的方式。可选值:
row
– 指示自动摆放算法按行的顺序按需增加新项目元素 (默认)column
– 指示自动摆放算法按列的顺序按需增加新项目元素dense
- 指示自动摆放算法尽量优先使用更小的项目元素摆放
例如,只指定区域 a、e 时:
.item-a {
grid-column: 1;
grid-row: 1 / 3;
}
.item-e {
grid-column: 5;
grid-row: 1 / 3;
}
2
3
4
5
6
7
8
<section class="container">
<div class="item-a">item-a</div>
<div class="item-b">item-b</div>
<div class="item-c">item-c</div>
<div class="item-d">item-d</div>
<div class="item-e">item-e</div>
</section>
2
3
4
5
6
7
如果使用 row
则效果为:
.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: row;
}
2
3
4
5
6
如果使用 column
则效果为:
.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: column;
}
2
3
4
5
6
grid
以下属性的简写形式:
- grid-template-rows
- grid-template-columns
- grid-template-areas
- grid-auto-rows
- grid-auto-columns
- grid-auto-flow
.container {
grid: 100px 300px / 3fr 1fr;
}
.container {
grid-template-rows: 100px 300px;
grid-template-columns: 3fr 1fr;
}
2
3
4
5
6
7
8
.container {
grid: auto-flow / 200px 1fr;
}
.container {
grid-auto-flow: row;
grid-template-columns: 200px 1fr;
}
2
3
4
5
6
7
8
.container {
grid: auto-flow dense 100px / 1fr 2fr;
}
.container {
grid-auto-flow: row dense;
grid-auto-rows: 100px;
grid-template-columns: 1fr 2fr;
}
2
3
4
5
6
7
8
9
.container {
grid: 100px 300px / auto-flow 200px;
}
.container {
grid-template-rows: 100px 300px;
grid-auto-flow: column;
grid-auto-columns: 200px;
}
2
3
4
5
6
7
8
9
.container {
grid: [row1-start] "header header header" 1fr [row1-end]
[row2-start] "footer footer footer" 25px [row2-end]
/ auto 50px auto;
}
.container {
grid-template-areas:
"header header header"
"footer footer footer";
grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
grid-template-columns: auto 50px auto;
}
2
3
4
5
6
7
8
9
10
11
12
13
项目元素属性
注意 设为 grid 布局以后,容器项目的 float、display: inline-block、display: table-cell、vertical-align 和 column-* 等设置都将失效。
grid-column-start,grid-column-end,grid-row-start,grid-row-end
依据网格线来定义网格元素在网格中的位置。可选值为:
- {grid line} – 网格线的数字序号或名字
- span {number} – 合并指定 number 数量的网格 track
- span {name} – 合并至指定的 name 网格线处
- auto – 浏览器自动计算
.item {
grid-column-start: 2;
grid-column-end: five;
grid-row-start: row1-start;
grid-row-end: 3;
}
2
3
4
5
6
.item {
grid-column-start: 1;
grid-column-end: span col4-start;
grid-row-start: 2;
grid-row-end: span 2;
}
2
3
4
5
6
如果未指定 end 值,项目只会穿过 1 个 track 。
grid-column,grid-row
grid-column
是 grid-column-start
grid-column-end
的简写形式, grid-row
是 grid-row-start
grid-row-end
的简写形式。
.item {
grid-column: 3 / span 2;
grid-row: third-line / 4;
}
2
3
4
grid-area
共有两个用法,一是配合 grid-template-areas
使用,用来指定区域名:
.item {
grid-area: header;
}
2
3
另外,还可以作为 grid-row-start
grid-column-start
grid-row-end
grid-column-end
的简写形式:
.item {
grid-area: 1 / col4-start / last-line / 6;
}
2
3
justify-self
其效果同 justify-items
,但只针对指定的项目生效。
align-self
其效果同 align-items
,但只针对指定的项目生效。
place-self
align-self
justify-self
的简写形式:
特殊单位和函数
fr
fr
表示剩余空间中的一部分,如下例表示 2 列分别占 25%、75% 。
grid-template-columns: 1fr 3fr;
其与百分比的区别在于:如果存在 padding(如下例中的 padding:50px),%
将会导致宽度不再是 100%;而 fr
不会造成该问题。
单位 fr
计算的是去除所有非弹性项目后的空间,如:
.container {
grid-template-columns: 1fr 50px 1fr 1fr;
}
2
3
会用总宽度减去 50px 后再将剩余空间三等分给 1、3、4 列。显然,单位 fr
在与其它单位联合使用时更为友好:
grid-template-columns: 50px min-content 1fr;
min-content
依据其内容的最小尺寸显示:
.container {
display: grid;
grid-template-columns: min-content 1fr 1fr;
gap: 10px;
}
2
3
4
5
<div class="container">
<div class="item">The very long hotdog.</div>
<div class="item"></div>
<div class="item"></div>
</div>
2
3
4
5
max-content
依据其内容的最大尺寸显示:
.container {
display: grid;
grid-template-columns: max-content 1fr 1fr;
gap: 10px;
}
2
3
4
5
<div class="container">
<div class="item">The very long hotdog.</div>
<div class="item"></div>
<div class="item"></div>
</div>
2
3
4
5
fit-content
在 min-content
与 max-content
之间调整可用空间:
.container {
display: grid;
grid-template-columns: fit-content 1fr 1fr;
gap: 10px;
}
2
3
4
5
<div class="container">
<div class="item">The very long hotdog.</div>
<div class="item"></div>
<div class="item"></div>
</div>
2
3
4
5
PS: 当前 Chrome (97.0.4692.99) 不支持该关键字。
minmax()
即长度所允许的最小、最大值,因此它限定了一个长度范围。通常配合其它相对单位使用时非常方便。
repeat()
网格很多时,可简化重复的值。repeat()
接受两个参数:1)重复的次数; 2)所要重复的值。
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
/* 简写为: */
grid-template-columns: repeat(8, 1fr);
2
3
有时单元格的大小是固定的,但是容器的大小不确定。如果希望一行(或列)容纳尽可能多的单元格,可以配合 auto-fill 关键字自动填充。
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr))