Grid 网格布局

总体概括
Flexbox(弹性盒)用于一维布局 — 也就是行或者列

网格用于二维布局 — 也就是多行多列

网格线

网格线是用来在水平和垂直方分割网格的线。水平方向的网格线是从左向右;垂直方向是从上往下;网格线的序号都是从 1 开始的。

图片内容

网格容器上的属性

grid-template-colums

描述:根据值得个数决定网格有多少列,每个值决定对应网格列的宽度

属性值:

  • 若干个以空格分割的长度值、百分比、fr
  • subgrid 如果你的网格容器本身就是一个网格项,可以使用该值指定行和列大小继承与父元素

grid-template-rows

描述:根据值的个数决定网格有多少行,每个值决定对应网格行的高度

  • 若干个以空格分割的长度值、百分比、fr
  • subgrid 如果你的网格容器本身就是一个网格项,可以使用该值指定行和列大小继承与父元素

grid-template-areas

描述:使用 grid-area 属性定义网格区域名称,从而定义网格模板。网格区域重复的名称就会导致内容跨越这些单元格。句点表示一个空单元格。语法本身提供了一种可视化的网格结构。

属性值:

  • : 使用grid-area属性定义的网格区域名称
  • . : 句点表示一个空的单元格
  • none : 无网格区域被定义

grid-column-gap 和 grid-row-gap

描述:指定网格线的大小,你可以吧他想象成在 行/列 之间的间距

属性值:长度值

注意:间距只在 行/列 之间产生,不会再边缘区

grid-gap

描述:grid-column-gap 和 grid-row-gap 的简写

属性值:以空格分割的长度值

justify-items

描述:沿列轴对齐网格项目中的内容(水平对齐);适用于网格容器

属性值:

  • start: 内容与网格区域的左端对齐
  • end: 内容与网格区域的右端对齐
  • center: 内容处于网格区域的中间位置
  • stretch: 内容宽度占据整个网格区域空间(默认值)

补充:也可以使用 justify-self 属性对单个的网格项目进行设置

align-items

描述:垂直对齐;适用于网格容器

属性值:

  • start: 内容与网格区域的顶端对齐
  • end: 内容与网格区域的底部对齐
  • center: 内容处于网格区域的中间位置
  • stretch: 内容高度占据整个网格区域空间(默认值)

补充:也可以使用 align-self 属性对单个网格项目对齐

justify-content

描述:当你使用px这种非响应式的单位对你的网格项进行大小设置时,就有可能出现一种情况–你的网格大小可能小于其网格容器的大小。在这种情况下,你就可以设置网格容器内网格的对齐方式。此属性会将网格沿列轴进行对齐(相反于align-content属性定义的沿行轴对齐)。非响应式的水平对齐

属性值:

  • start: 网格与网格容器的左端对齐
  • end: 网格与网格容器的右端对齐
  • center: 网格处于网格容器的中间
  • stretch: 调整网格项的大小,使其宽度填充整个网格容器
  • space-around: 在网格项之间设置偶数个空格间隙,其最边缘间隙大小为中间空格间隙大小的一半
  • space-between: 在网格项之间设置偶数个空格间隙,其最边缘不存在空格间隙
  • space-evenly: 在网格项之间设置偶数个空格间隙,同样适用于最边缘区域

align-content

描述:当你使用px这种非响应式的单位对你的网格项进行大小设置时,就有可能出现一种情况–你的网格大小可能小于其网格容器的大小。在这种情况下,你就可以设置网格容器内网格的对齐方式。此属性会将网格沿行轴进行对齐(相反于justify-content属性定义的沿列轴对齐)。非响应式垂直对齐。

属性值:

  • start: 网格与网格容器的顶端对齐
  • end: 网格与网格容器的底部对齐
  • center: 网格处于网格容器的中间
  • stretch: 调整网格项的大小,使其高度填充整个网格容器
  • space-around: 在网格项之间设置偶数个空格间隙,其最边缘间隙大小为中间空格空隙大小的一半
  • space-between: 在网格项之间设置偶数个空格间隙,其最边缘不存在空格间隙
  • space-evenly: 在网格项之间设置偶数个空格间隙,同样适用于最边缘区域

grid-auto-columns 和 grid-auto-rows

描述:指定任何自动生成的网格轨道(隐式网格跟踪)的大小。当你显式定位行或列(使用 grid-template-rows/grid-template-columns属性)时,就会产生超出定义范围内的隐式网格轨道。

属性值:长度值、百分比、fr

grid-auto-flow

描述:如果你不显式的在网格中放置网格项,自动布局算法就会自动踢出此网格项。此属性用来控制自动布局算法的工作原理。

属性值:

  • row: 告诉自动布局算法填充每一行,必要时添加新行(默认:以填充行为准)
  • column: 告诉自动布局算法填充每一列,必要时添加新列(以填充列为准)
  • dense: 告诉自动布局算法试图填补网格中之前较小的网格项留有的空白

注意:dense值可能会导致更改网格项的顺序。

grid

描述:在一行声明中设置一下所有属性的简写形式:grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, 以及 grid-auto-flow。它将 grid-column-gapgrid-row-gap属性设置为初始值,即使它们不能显示的设置此属性。

属性值:

  • none: 将所有的子属性设置为初始值
  • subgrid: 将grid-template-rowsgrid-template-columns属性值设置为subgrid,其余子属性设置为初始值
  • / : 将grid-template-rowsgrid-template-columns属性值设置为指定值,其余子属性设置为初始值
  • [ [ / ] ] : grid-auto-flow, grid-auto-rowsgrid-auto-columns属性分别接受相同的值,如果省略了grid-auto-columns属性,它将设置为grid-auto-rows属性的值。如果两者均被忽略,那么都将被设置为初始值。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 等效代码块1
.container{
grid: 200px auto / 1fr auto 1fr;
}

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

// 等效代码块2
.container{
grid: column 1fr / auto;
}

.container{
grid-auto-flow: column;
grid-auto-rows: 1fr;
grid-auto-columns: auto;
}

// 等效代码块3
.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;
}

加在网格项上的属性

grid-column-start:设置网格项目垂直方向的开始位置网格线

grid-column-end:设置网格项目垂直方向的结束位置网格线

grid-row-start:设置网格项目水平方向的开始位置网格线

grid-row-end:设置网格项目水平方向的结束位置网格线

注意:以上属性的初始值都是 auto

属性值:

  • : 可以是一个数字来引用相应编号的网格线,或者使用名称引用相应命名的网格线
  • span : 网格项包含指定数量的网格轨道
  • span : 网格项包含指定名称网格项的网格线之前的网格轨道
  • auto: 表明自动定位,自动跨度或者默认跨度之一

网格项目属性的缩写

grid-column:是grid-column-startgrid-column-end两个属性的缩写方式

grid-row:是grid-row-startgrid-row-end两个属性的缩写方式

grid-area:是这四个属性的缩写方式grid-row-start / grid-column-start/ grid-row-end / grid-column-end

给网格项进行命名以便于模板使用grid-template-areas属性创建时可以加以引用。另外也可以被grid-row-start + grid-column-start + grid-row-end + grid-column-end属性更为简洁的加以引用。

特别声明grid-rowgrid-columngrid-area采用缩写时,前后两个值之间需要使用/分割线分开(/分割线之间最好添加一个空格号)。

justify-self

描述:水平对齐网格项

属性值:

  • start: 内容与网格区域的左端对齐
  • end: 内容与网格区域的右端对齐
  • center: 内容处于网格区域的中间位置
  • stretch: 内容宽度占据整个网格区域空间(默认值)

align-self

描述:垂直对齐

属性值:

  • start: 内容与网格区域的顶端对齐
  • end: 内容与网格区域的底部对齐
  • center: 内容处于网格区域的中间位置
  • stretch: 内容高度占据整个网格区域空间(默认值)

单元格跨越(合并单元格)

span 关键词可以实现但单元格的跨越

两个等价的写法:

1
2
3
4
5
6
7
8
9
10
11
// span 关键字写法
.item-2{
grid-column: 2 / span 2;
grid-row: 1;
}

// 之前的写法
.item-2{
grid-colums: 2 / 4;
grid-row: 1 / 2;
}

注意:你会发现 grid-row 并没有设置 grid-row-end 的网格线。这意味着其值为 auto,自动默认为 span 的值为 1

负的网格线序号

负的网格线序号会从 -1 开始反方向计算,如下图

网格线序列为负值,在某些情况下是有用的,例如,想让某个网格项目始终在最后一列,这个时候只需要设置 grid-column-end : -1

网格线命名

网格线除了使用数字来表示之外,还可以给每条网格线命名

在定义网格的时候,除了设置网格轨道大小之外,在此基础上增加网格线的命名,如下示例:

1
2
3
4
5
6
7
8
9
10
.grid-1 {
display: grid;
grid-template-columns: [start] 300px [main] 200px [aside] 100px [end];
grid-template-rows: [top] 100px [middle] 50px [bottom];
}

.item-2 {
grid-column: main / end;
grid-row: top / middle;
}

对于上述代码命名演示,有如下图的描述

其实一条网格线可以有多个名字,如下示例代码:

1
2
grid-template-columns: [start] 300px [main] 200px [aside] 100px [end];
grid-template-rows: [top start] 100px [middle center] 50px [bottom end]

网格线还可以重复命名,并且可以使用正负值,下面的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
.grid-1 {
display: grid;
width: 100%;
max-width: 600px;
margin: 0 auto;
grid-template-columns: [col] 200px [gap] 50px [col] 200px [gap] 50px [col] 200px [gap];
}

.item-2 {
grid-column: col 2;
}

.item-3 {
grid-column: col 3;
}

.item-4 {
grid-column: col 1 / gap 2;
}

.item-5 {
grid-column: col -1;
}

上述代码对应网格示例图

grid-column 一个值的时候表示开始网格线,负数的时候表示倒着数的序列

补充:span 除了可以跨越网格数,还可以跨越网格线的名称

规则:跨域的网格线名称结束网格线计数为开始网格线往后计数(不含开始网格线),如果数字超出网格线名称出现的次数,则占据一行的剩下所有列。

示例:

1
2
3
.item-2{
grid-column:col 2 / span 2 gap
}

网格区域

根据之前学习的内容,可以通过网格线构造出网格区域

HTML:

1
2
3
4
5
6
7
8
<section class="grid-1">
<div class="item-1">1</div>
<div class="item-2">2</div>
<div class="item-3">3</div>
<div class="item-4">4</div>
<div class="item-5">5</div>
<div class="item-6">6</div>
</section>

CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
body {
padding-top: 40px;
background: #f5f7f8;
}

.grid-1 {
display: grid;
width: 100%;
max-width: 600px;
margin: 0 auto;
grid-template-columns: 300px 200px 100px;
grid-template-rows: 100px 50px;
}
.grid-1 div {
color: white;
font-size: 20px;
padding: 20px;
}
.grid-1 div:nth-child(1) {
background: #b03532;
}
.grid-1 div:nth-child(2) {
background: #33a8a5;
}
.grid-1 div:nth-child(3) {
background: #30997a;
}
.grid-1 div:nth-child(4) {
background: #6a478f;
}
.grid-1 div:nth-child(5) {
background: #da6f2b;
}
.grid-1 div:nth-child(6) {
background: #3d8bb1;
}

.item-1 {
grid-area: 1 / 1 / 2 / 4;
}

.item-2 {
grid-area: 2 / 1 / 4 / 2;
}

.item-4 {
grid-area: 2 / 3 / 4 / 4;
}

.item-6 {
grid-area: 4 / 1 / 5 / 4;
}

除此之外还可以直接定义网格区域,用来放置对应的网格项目

Grid 布局使用 grid-template-areas 属性来声明,然后使用 grid-area 调用声明好的网格区域名称来放置对应的网格项目。

HTML:

1
2
3
4
5
6
7
<section class="grid">
<div class="title">title</div>
<div class="nav">nav</div>
<div class="main">main</div>
<div class="aside">aside</div>
<div class="footer">footer</div>
</section>

CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
body{
padding-top: 40px;
background: #ccc;
}
.grid{
display: grid;
width: 100%;
margin: 0 auto;
grid-template-columns: 100px 100px 100px 100px 100px;
grid-template-rows: 100px 100px 100px 100px;
grid-template-areas:
'title title title title aside'
'nav main main main aside'
'nav main main main aside'
'footer footer footer footer footer';
}

.grid div:nth-child(1) {
background: #b03532;
}
.grid div:nth-child(2) {
background: #33a8a5;
}
.grid div:nth-child(3) {
background: #30997a;
}
.grid div:nth-child(4) {
background: #6a478f;
}
.grid div:nth-child(5) {
background: #da6f2b;
}

.title{
grid-area: title;
}
.nav{
grid-area: nav;
}
.main{
grid-area: main;
}
.aside{
grid-area: aside;
}
.footer{
grid-area: footer;
}

以上代码对应的图像:

网格区域和网格线命名

网格线的隐名可以创建网格区域,这些隐名使用 -start 和 -end 后缀添加到网格区域名后面,例如:上例中的 title 区域创建了4 条网格线的隐名:

  • 区域左边的网格线title-start
  • 区域右边的网格线title-end
  • 区域顶边的网格线title-start
  • 区域底边的网格线title-end

在使用 grid-template-areas 创建网格区域以后,就隐式的声明了网格线名称,反过来,如果在grid-template-coumns 和 grid-template-rows 中使用了隐式的网格线名称也就默认创建了网格区域

在网格布局中,如果使用了带有后缀的名词命名了网格线,其实就创建了一个隐式的网格区域,示例:

HTML:

1
2
3
4
5
6
7
<section class="grid">
<div class="title">title</div>
<div class="nav">nav</div>
<div class="main">main</div>
<div class="aside">aside</div>
<div class="footer">footer</div>
</section>

CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
body {
padding-top: 40px;
background: #f5f7f8;
}

.grid {
display: grid;
width: 100%;
max-width: 500px;
margin: 0 auto;
grid-template-columns: [title-start nav-start footer-start] 100px [main-start nav-end] 100px 100px 100px [aside-start title-end main-end] 100px [aside-end footer-end];
grid-template-rows: [title-start aside-start] 100px [nav-start main-start title-end] 100px 100px [footer-start nav-end main-end aside-end] 100px [footer-end];
}
.grid div {
color: white;
font-size: 20px;
padding: 20px;
}
.grid div:nth-child(1) {
background: #b03532;
}
.grid div:nth-child(2) {
background: #33a8a5;
}
.grid div:nth-child(3) {
background: #30997a;
}
.grid div:nth-child(4) {
background: #6a478f;
}
.grid div:nth-child(5) {
background: #da6f2b;
}

.title {
grid-area: title;
}

.nav {
grid-area: nav;
}

.main {
grid-area: main;
}

.aside {
grid-area: aside;
}

.footer {
grid-area: footer;
}

有了带后缀的网格线名称也就有了隐式的网格区域,有了网格区域也就自动有了网格线的隐式名,只要有其中一个就可以用任意两种方式设置网格区域,在思维上一般是先规划好网格区域之后才知道网格线的名称。

网格轨道

网格轨道其实就是网格的行或列。就是网格中相邻两条网格线组成的区域

网格中的每个轨道都有一个尺寸函数,用来控制行的高度或列的宽度。而且还具备自动计算的功能,当内容超过网格行、列指定的尺寸时,会自动增加行的高度或列的宽度,相邻网格轨道可以通过网格间距隔开。

单元格

网格单元格是指网格行和列交叉点。他是一个定位网格项目时要参考的网格的最小单位

在网格布局中,多个单元格可以构成一个网格区域。

声明网格和网格容器

在CSS中,声明网格主要方式就是通过给某个容器的display设置为gridinline-grid或者subgrid值之一。同时这个容器就被称为网格容器,而这个容器的子元素就称为网格项目

网格容器不是块容器(display:block),因此在块容器中的一些属性使用并不适用于网格容器当中:

  • 多列布局属性column-*不能用于网格容器
  • 浮动和清除浮动,对于网格项目中使用不生效。但是,浮动的属性对于网格容器的子元素还是生效的
  • vertical-align属性对于网格项目不生效
  • ::first-line::first-letter伪元素不能用于网格容器

在 Grid 布局中,通过 grid-template-columns 和 grid-template-rows 确定一个网格的列数,、行数以及网格的大小

grid-template-columns grid-template-rows grid-template-areas 三个属性可以显示创建一个网格容器,三个属性可以简写成 grid-template

综合属性的书写方式为: grid-template: rows / columns

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 等价的书写方式
grid-template: auto 1fr / auto 1fr auto;

// 以上等价于以下
grid-template-rows: auto 1fr;
grid-template-columns: auto 1fr auto;
grid-template-areas: none;

// 三个属性混合书写与等价写法
grid-template: [header-top] "a a a" [header-bottom]
[main-top] "b b b" 1fr [main-bottom]
/ auto 1fr auto;

grid-template-areas: "a a a"
"b b b";
grid-template-rows: [header-top] auto [header-bottom main-top] 1fr [main-bottom];
grid-template-columns: auto 1fr auto;

隐式网格

使用 grid-auto-rows 和 grid-auto-columns 可以创建一个隐式网格,隐式单元格不确定列数或行数,具体的列数和行数根据 grid-column 或 grid-row 而定,而显示网格则已经确定行数或列数

隐式网格就是在使用 grid-template-columns 和 grid-template-rows 的时候可能只定义了1 行 2 列,但是在通过 grid-column 指定网格的位置的时候指定到了第 5 列,此时这是额外增加的网格,该网格宽高则遵循隐式网格的声明,如果没有设置隐式网格那么新增网格宽高会根据剩余空间自动确定

在没有定义隐式网格新增网格的情况下自适应规则为:在显式网格后追加一个隐式网格默认宽度占据剩余宽度,追加多个隐式网格则隐式网格平分剩余空间,跳过 x 网格数创建的隐式网格和追加多个网格规则一样

grid-auto-columns 可以给多个以空格分割的长度值,该长度值将被重复应用于后来添加的隐式网格区域

合并单元格也会创建隐式网格,例如给一行中的最后一个项目设置跨列就会创建隐式的列

隐式的轨道也可以在显示网格轨道前添加,使用 grid-column 属性的负值就可以做到

隐式网格和网格线命名

创建隐式的网格还可以通过使用未定义的网格线名称来创建,在 grid-column 中使用未定义的网格线名称会隐式定义后面网格线都为该网格线名称。示例为一个未定义的 foo 网格线名称

网格容器的无效属性:column float clear vertical-align

repeat()**

在大量行或列重复的时候,可以使用repeat

1
2
3
4
5
6
7
// 一个等价写法的示范
grid-template-columns: 10px [col-start] 250px [col-end]
10px [col-start] 250px [col-end]
10px [col-start] 250px [col-end]
10px [col-start] 250px [col-end] 10px;

grid-template-columns: repeat(4, 10px [col-start] 250px [col-end]) 10px;

repeat() 语法:

repeat(重复次数, 待重复列表)

网格间隔

grid-column-gap 定义列的间隔距离

grid-row-gap 定义行的间隔距离

grid-gap 定义行和列的间隔距离

grid-template 是 grid-template-rows grid-template-columns grid-template-areas 的简写

1
grid-temnplate:auto 1fr / auto 1fr auto

网格重叠与排序

网格之间可以重叠,层级关系使用 z-index 指定

网格可以排序,使用 order 指定顺序