15Grid 布局中的对齐方式
# 本资源由 itjc8.com 收集整理
CSS 网格布局除了提供定义网格和放置网格项目的相关属性之外,也提供了一些控制对齐方式的属性。这些控制对齐方式的属性,和 Flexbox 布局中的对齐属性 justify-* 、align-* 、*-items 、*-content 、 *-self 等是相似的:
在网格布局中可以用它们来控制网格项目在内联轴(Inline Axis)和块轴(Block Axis)的对齐方式;也可以用来控制网格轨道在内联轴(Inline Axis)和块轴(Block Axis)的对齐方式。
接下来,在这节课程中,我将演示网格布局中的对齐方式是如何工作的,你会发现很多属性和值与 Flexbox 布局中的用法是类似的(Flexbox 布局对齐方式请参阅读前面课程:《04 | Flexbox 布局中的对齐方式 (opens new window) 》)。不过,网格布局是二维的,Flexbox 布局是一维的,所以你也会发现它们有一些小区别。我们就从处理网格对齐时用到的两条轴线开始吧。
# 网格布局中的轴线
对于大多数开发者来说,他们都知道 Web 有两根轴线:水平方向的 x 轴和垂直方向的 y 轴。只不过,在 Flexbox 布局中,不再称 x 轴和 y 轴了,它由 Flexbox 中的主轴(Main Axis)和侧轴(Cross Axis)替代了,并且 Flexbox 的主轴不再绝对的是 x 轴,侧轴也不再绝对的是 y 轴,它由 flex-direction 属性的值来决定:
由于网格布局是唯一的二维布局,因此,网格布局中也有两条轴线,这两条轴线既不称为水平的 x 轴和垂直方向的 y 轴,也不像 Flexbox 布局中称为主轴和侧轴。它们有着新命名的两条轴线,即内联轴(Inline Axis)和块轴(Block Axis):
- 内联轴(Inline Axis) :主要定义网站的文本流方向,也就是文本的阅读方式,CSS 的
direction或 HTML 的dir会影响内联轴的方向。 - 块轴(Block Axis) :主要定义网站文档(元素块)流,CSS 的书写模式
writing-mode会影响块轴的方向。
即,内联轴和块轴会受 CSS 的 direction 、writing-mode 和 HTML 的 dir 属性值的影响,这个有点类似于 Flexbox 布局的主轴和侧轴,不是固定不变的:
网格布局中的内联轴(Inline Axis)和块轴(Block Axis)可以和网格中的行与列相映射,比如书写模式和阅读模式是 ltr(Left-To-Right)时,内联轴也称为行轴(Row Axis),块轴也称为列轴(Column Axis):
需要注意的是,虽然内联轴(Inline Axis)和块轴(Block Axis)会因 CSS 的书写模式或文档的阅读模式改变,但网格中的行轴和列轴是始终不变的:
网格布局中,你就可以沿着这两条轴线来控制网格项目或网格轨道的对齐方式。
特别声明,如无特别指出,我们都以书写模式和阅读模式是
ltr(Left-To-Right)为例,即可内联轴对应的是行轴,块轴对应的是列轴 。
# 网格布局中的对齐方式
在 Flexbox 布局中,可以在 Flex 容器的主轴和侧轴方向控制 Flex 项目的对齐方式。在 Grid 布局中,将按照内联轴和块轴两个方向来控制 网格轨道 和 网格项目 的对齐方式:
- 控制“网格项目”沿块轴方向的对齐属性有:
align-items和align-self,其中align-items运用于网格容器上,align-self运用于网格项目上。 - 控制“网格项目”沿内联轴方向的对齐属性有:
justify-items和justify-self,其中justify-items运用于网格容器上,justify-self运用于网格项目上。 - 控制“网格轨道”沿块轴方向对齐的属性有:
align-content,该属性运用于网格容器上。 - 控制“网格轨道”沿内联轴方向对齐的属性有:
justify-content,该属性运用于网格容器上。
也可以按下面这样的方式来划分:
- 对齐网格项目 :
justify-items和justify-self沿着内联轴方向对齐网格项目,而align-items和align-self沿着块轴方向对齐网格项目,其中justify-items和align-items被运用于网格容器,而justify-self和align-self被运用于网格项目。 - 对齐网格轨道 :
align-content沿着块联轴方向对齐网格轨道,justify-content沿着内联轴方向对齐网格轨道,它们都被运用于网格容器。
我们先来看网格项目的对齐。
# 网格项目对齐
控制网格项目的对齐方式的属性主要有:
justify-items和justify-self控制网格项目沿着内联轴(文本书写方向的行轴)方向对齐;align-items和align-self控制网格项目沿着块轴(块方向的列轴)方向的对齐。
这几个属性都可以接受 auto 、normal 、start 、end 、center 、stretch 、 baseline 、first baseline 和 last baseline 值,但常用的值只有 start 、end 、center 和 stretch (默认值)。其中 start 、center 和 end 表示相应轴的起点位置,中心位置和终点位置:
注意,这几个属性都是用来控制网格项目在所处网格区域内的内联轴或块轴方向的对齐,如果没有跨网格单元格,则在对应的网格单元格内的内联轴或块轴方向的对齐。
假设你有下面这样的一个网格:
<div class="container">
<div class="item"></div>
<!-- 此处省略四个 item -->
<div class="item"></div>
</div>
.container {
display: grid;
gap: 1rem;
grid-template-columns: repeat(8, 1fr);
grid-auto-rows: 80px;
grid-auto-columns: 80px;
grid-template-areas:
"a a a a b b b b"
"a a a a b b b b"
"c c c c d d d d"
"c c c c d d d d";
}
.item:nth-child(1) {
grid-area: a;
}
.item:nth-child(2) {
grid-area: b;
}
.item:nth-child(3) {
grid-area: c;
}
.item:nth-child(4) {
grid-area: d;
}
.item:nth-child(5) {
grid-row: 1 / -1;
grid-column: span 2;
}
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
上面的代码构建了一个四行十列(4 x 10)的隐式网格,并且使用 grid-area 分别将网格项目放置到指定的网格区域:
- 网格项目一放置在网格区域
a; - 网格项目二放置在网格区域
b; - 网格项目三放置在网格区域
c; - 网格项目四放置在网格区域
d。
使用 grid-row 和 grid-column 将网格项目五放置指定的区域内(合并四行两列),相当于放置在 grid-area: 1 / 9 / 5 ``/`` 11 区域内:
你可以在网格容器上显式设置 align-items 属性的值,比如:
.container {
align-items: var(--align-items, stretch);
}
2
3
正如上图所示:
start将网格项目和所处网格区域在块轴的起始位置重叠;end将网格项目和所处网格区域在块轴的结束位置重叠;center将网格项目和所处网格区域在块轴中心位置重叠(类似垂直居中);stretch将网格项目拉伸与所处网格区域高度相同,相当于与网格区域的块轴方向起始、结束位置同时重叠(类似垂直方向的拉伸)。
另外,align-items 取值为 auto 、normal 和 last baseline 值时,与取值 stretch 值效果等同;baseline 和 first baseline 的效果与 start 等同:
Demo 地址:https://codepen.io/airen/full/zYavJow
一旦在网格容器上设置了 align-items 的值是 stretch 的其他值之后,所有网格项目的高度(块轴方向尺寸,block-size)都将会由其内容的高度决定。另外,在网格容器上显式设置了 align-items 的值,就相当于在所有网格项目上设置了 align-self 的值。比如:
.container {
align-items: var(--align-items, stretch);
}
/* 等同于 */
.container > * {
align-self: var(--align-items, stretch);
}
2
3
4
5
6
7
8
当然,你也可以在单个网格项目上显式设置 align-self 的值:
.item:nth-child(1) {
align-self: start;
}
.item:nth-child(2) {
align-self: end;
}
.item:nth-child(3) {
align-self: center;
}
2
3
4
5
6
7
8
9
10
11
Demo 地址: https://codepen.io/airen/full/VwdvELO
你可以同时显式设置网格容器的 align-items 和单个网格项目的 align-self 的值,只不过最终由网格项目上的 align-self 值来决定(没有显式设置 align-self 的网格项目则由 align-items 决定)。比如:
.container {
align-items: var(--align-items, stretch);
}
.item:nth-child(1) {
align-self: center;
}
2
3
4
5
6
7
上面这个示例,网格项目一在块轴方向始终是是垂直居中的,因为它显式设置了 align-self 的值为 center ,其他网格项目在块轴的对齐方式则由网格容器上的 align-items 属性的值来决定:
Demo 地址: https://codepen.io/airen/full/NWzGOpp
与 align-items 和 align-self 相似的是,你可以在网格容器上设置 justify-items 属性和在网格项目上设置 justify-self 属性,控制网格项目在内联轴的对齐方式。比如:
.container {
justify-items: var(--justify-items, stretch);
}
2
3
正如上图所示:
start将网格项目和所处网格区域在内联轴的起始位置重叠;end将网格项目和所处网格区域在内联轴的结束位置重叠;center将网格项目和所处网格区域在内联轴中心位置重叠(类似水平居中);stretch将网格项目拉伸与所处网格区域宽度相同,相当于与网格区域的内联轴方向起始、结束位置同时重叠(类似水平方向的拉伸)。
同样的,justify-items 取值是 auto 、normal 和 last baseline 时与 stretch 值效果等同;baseline 和 first baseline 的效果与 start 等同:
Demo 地址: https://codepen.io/airen/full/gOKaBvw
和 align-items 一样,当你在网格容器上设置了 justify-items 时,就等同于在所有网格项目上设置了 justify-self :
.container {
justify-items: var(--justify-items, stretch);
}
/* 等同于 */
.container > * {
justify-self: var(--justify-items, stretch);
}
2
3
4
5
6
7
8
你也可以根据需要,在网格项目上单独设置 justify-self 属性的值,控制单独网格项目在内联轴方向的对齐:
.item:nth-child(1) {
justify-self: start;
}
.item:nth-child(2) {
justify-self: center;
}
.item:nth-child(3) {
justify-self: end;
}
2
3
4
5
6
7
8
9
10
11
Demo 地址: https://codepen.io/airen/full/qBKOJLW
如果在网格容器上设置了 justify-items 属性的值,并且在网格项目上也显式设置了 justify-self 属性的值,那么最终网格项目在内联轴方向的对齐由 justity-self 属性的值来决定。比如:
.container {
justify-items: var(--justify-items, stretch);
}
.item:nth-child(1) {
justify-self: center;
}
2
3
4
5
6
7
Demo 地址: https://codepen.io/airen/full/RwJWeOG
你可能已经发现了,当 justify-items 或 justify-self 属性的值不是默认值 strecth 时,网格项目的宽度(内联轴方向的尺寸,inline-size)就会发生变化,与 auto 值相似。
在网格布局中,justify-items 和 align-items 还可能简写成 place-items ;justify-self 和 align-self 可以简写成 place-self ,即:
place-items: <align-items> <justify-items>
place-self: <align-self> <justify-self>
2
当 place-items 和 place-self 只取一个值时,表示两个属性的值相同,否则第一个值用于 align-* ,第二个值则用于 justif-* ,比如:
.container {
place-items: center end;
/* 等同于 */
align-items: center;
justify-items: end;
}
.item:nth-child(1) {
place-self: center end;
/* 等同于 */
align-self: center;
justify-self: end;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
注意,
justify-items和justify-self两属性不能运用于 Flexbox 布局,主要是因为 Flexbox 布局是一个一维布局,在单个轴上有很多个元素(Flex 项目),无法单独对齐其中某一个元素(Flex 项目) 。
不知道你是否已经发现了,在 Web 布局中,又多了两种实现水平居中的布局技术。在网格布局中,你可以使用下面这两种技术,让某个元素(Grid 项目)水平垂直居中在另一个元素(网格区域)中:
<div class="container">
<div class="item">我要水平垂直居中</div>
</div>
.container {
display: grid;
place-items: center;
/* 等同于 */
align-items: center;
justify-items: center;
}
.item {
grid-area: 1 / 1 / -1 / -1;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Demo 地址: https://codepen.io/airen/full/YzvyRGN
上面这个示例效果,你还可以在网格项目上使用 place-self 来替代网格容器上的 place-items :
.container {
display: grid;
}
.item {
grid-area: 1 / 1 / -1 / -1;
place-self: center;
/* 等同于 */
align-self: center;
justify-self: center;
}
2
3
4
5
6
7
8
9
10
11
12
13
Demo 地址:https://codepen.io/airen/full/qBKbwKp
再次强调一下,justify-items 、align-items 、justify-self 和 align-self 都是用来控制网格项目自身所处网格区域的内联轴和块轴方向的对齐,如果网格项目没有明确放置,将按自动放置的算法来计算网格区域,一般就是网格单元格,因为网格单元格也是一个网格区域,网格中默认的最小网格区域:
.container {
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: 120px;
gap: 1rem;
/* 设置所有网格项目在内联轴和块轴方向的对齐 */
place-items: var(--align-items, stretch) var(--justify-items, stretch)
}
/* 只设置网格项目一在内联轴和块轴方向的对齐 */
.item:nth-child(1) {
place-self: var(--align-self, stretch) var(--justify-self, stretch)
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Demo 地址:https://codepen.io/airen/full/xxzwQpV
用下面这张图来总结网格项目在内联轴和块轴上对齐方式的效果:
# 网格轨道对齐
CSS Grid 布局中的对齐方式和 Flexbox 布局中的对齐方式最大的不同之处是:
在网格布局中,除了可以控制网格项目在内联轴和块轴的方向对齐之外,还可以控制网格轨道在内联轴和块轴方向的对齐 。
在网格布局中,所有网格轨道尺寸所占据的空间可能会小于网格容器空间:
- 内联轴方向 :所有列网格轨道的尺寸总和小于网格容器内联轴方向的尺寸(
inline-size),即在grid-template-columns(或grid-auto-columns)定义的列轨道尺寸总和小于网格容器的宽度; - 块轴方向 :所有行网格轨道的尺寸总和小于网格容器块轴方向的尺寸(
block-size),即在grid-tempalte-rows(或grid-auto-rows)定义的行轨道尺寸总和小于网格容器高度。
这样你就可以分别在网格容器的:
- 内联轴方向 :
justify-content控制列网格轨道在内联轴方向的对齐方式,即控制网格列的对齐; - 块轴方向 :
align-content控制行网格轨道在块轴方向的对齐方式,即控制网格行的对齐。
它们(justify-content 和 align-content 属性)可设置的值是:normal 、start 、end 、center 、stretch 、space-around 、space-between 、space-evenly 、baseline 、first baseline 和 last baseline 。
同样的,我们使用下面这个示例来向大家展示 justify-content 和 align-content 取不同值的效果会是什么?
假设你有一个 500px x 500px 的网格容器,即网格容器的内联轴方向的尺寸(inline-size)和块轴方向尺寸(block-size)都是 500px 。使用 grid-template-columns 和 grid-template-rows 定义了一个三行三列(3 x 3 )的网格,并且网格轨道尺寸都是 100px ,同时网格轨道之间有 10px 的间距:
.container {
inline-size: 500px;
block-size: 500px;
display: grid;
gap: 10px;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
}
2
3
4
5
6
7
8
9
10
可以像 Flexbox 布局中的 justify-content 和 align-content 一样,将剩余空间分配到网格轨道之间。
在网格容器上将 align-content 设置不同值:
.container {
align-content: var(--align-content, start);
}
2
3
Demo 地址:https://codepen.io/airen/full/MWXKjVj
你会发现,在这个示例中,align-content 取值为 normal 、stretch 、baseline 、first baseline 、last baseline 的效果与 start 是等同的。事实上,algin-content 取值 stretch 时会对网格轨道进行拉伸,但并不是所有情景都是如此,它对网格轨道尺寸的设置是有一定要求的。有关于这方面,我们将放到后面与 justify-content 统一阐述。
虽然说 align-content 是用来控制网格行轨道在网格容器块轴方向的对齐方式,但从另一个角度来说,也是将网格容器的剩余空间分配给网格轨道之间。比如:
align-content 取值为 center 时,网格容器的剩余空间将一分为二,第一行网格轨道在块轴的起始位置与网格容器块轴方向超始位置的距离等于最后一行网格轨道在块轴的结束位置与网格容器块轴方向结束位置的距离:
如果网格容器只有一行行网格轨道时,可以实现垂直居中的效果 。
align-content 取值为 space-around 时,分配给相邻两行网格道之间的网格容器的剩余空间,是第一行网格轨道块轴起始位置距网格容器块轴方向起始位置之间距离的两倍,也是最后一行网格轨道块轴结束位置距网格容器块轴方向结束位置之间距离的两倍。
align-content 取值 space-evenly 的效果和 space-around 有点相似,只不过,分配给相邻两行网格轨道之间的网格容器的剩余空间,和第一行网格轨道块轴方向起始位置与网格容器块轴方向起始位置之间的距离相等,也和最后一行网格轨道块轴方向结束位置与网格容器块轴方向结束位置之间的距离相等:
align-content 取值为 space-between 会令行网格轨道在网格容器块轴方向两端对齐,即网格容器的剩余空间会平均分配到相邻两行行网格轨道之间:
需要注意的是,当行网格轨道的尺寸是 fr 值时,align-content 取任何值的效果都和其默认值 start 等同。比如:
.container {
grid-template-rows: 1fr 100px 100px;
/* 或 */
grid-template-rows: minmax(100px, 1fr) 100px 100px;
/* 或 */
grid-auto-rows: 1fr;
}
2
3
4
5
6
7
8
9
Demo 地址: https://codepen.io/airen/full/poKgeMR
也就是说,当网格容器没有剩余空间时,align-content 各值的效果都相同,即等同于 align-content 的 start (默认值效果) 。
既然网格容器有剩余空间,也就有可能会有不足空间出现,比如将示例中的行网格轨道尺寸设置为:
.container {
grid-template-rows: 70% 120px 120px;
}
2
3
网格项目溢出网格容器:
Demo 地址: https://codepen.io/airen/full/dyKGWYa
网格项目溢出网格容器时,align-content 取值不同时,溢出方向也有所差异:
start,网格项目在网格容器块轴方向结束位置溢出;end,网格项目在网格容器块轴方向起始位置溢出;center,网格项目在网格容器块轴两个方向溢出;stretch与start等同;space-around与center等同;space-between与start等同;space-evenly与center等同。
在网格容器上显式设置 align-content 值时,还有可能会造成网格区域变大。比如下面这个示例,网格项目一合并了两行两列。当 align-content 取值 space-around 、sapce-evenly 和 space-between 时,行网格轨道之间的间距就会产生变化,这样对于合并多行的网格项目一来说,尺寸(块轴方向尺寸,block-size)也会产生相应变化:
.container {
inline-size: 500px;
block-size: 500px;
display: grid;
gap: 10px;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
}
.item:nth-child(1) {
grid-row: 1 / span 2;
grid-column: 1 / span 2;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Demo 地址:https://codepen.io/airen/full/OJEMmxN
上面看到的都是行网格轨道在网格容器块轴方向的对齐方式(分配网格容器块轴方向剩余空间)。接下来在前面的示例基础上,将 align-content 换成 justify-content 。
.container {
justify-content: var(--justify-content, start);
}
2
3
不难发现,justify-content 取值和 align-content 值效果是相同的,唯一不同的是, justify-content 是用来控制列网格轨道在网格容器的内联轴方向的对齐方式,即 分配网格容器内联轴方向的剩余空间 :
Demo 地址:https://codepen.io/airen/full/eYKJWer
justify-content 取值为 center 、space-around 、space-evenly 和 space-between 分配网格容器内联轴方向剩余空间如下:
注意,如果网格只有一列,****
justify-content取值center可以实现水平居中效果 。
如果 grid-tempalte-columns 或 grid-auto-columns 设置列网格轨道尺寸时,设置了 fr 单位值,那么 justify-content 取任何值的效果都与默认值 start 等同:
.container {
grid-template-columns: minmax(100px, 1fr) 100px 100px;
}
2
3
Demo 地址: https://codepen.io/airen/full/yLEeXOR
网格项目在内联轴方向溢出网格容器时,justify-content 取值不同,溢出方向也有所差异:
start,网格项目在网格容器内联轴方向结束位置溢出;end,网格项目在网格容器内联轴方向起始位置溢出;center,网格项目在网格容器内联轴两个方向溢出;stretch与start等同;space-around与center等同;space-between与start等同;space-evenly与center等同。
.container {
grid-template-columns: 70% 120px 120px;
}
2
3
Demo 地址:https://codepen.io/airen/full/oNybwWx
justify-content 和 align-content 一样,取值为 space-around 、space-evenly 和 space-between 会影响网格区域内联尺寸方向的尺寸(inline-size),即宽度会变大:
Demo 地址: https://codepen.io/airen/full/YzvwQrN
刚才有提到过,align-content 和 justify-content 在我们演示的示例中取值为 stretch 的效果和 start 是一样的。这主要是因为示例中的网格轨道尺寸是一个固定值,你可以尝试将示例中的 grid-template-columns 和 grid-template-rows 中的值调整为 auto 100px auto ,即有些轨道尺寸由内容来决定:
.container {
grid-template-columns: auto 100px auto;
grid-template-rows: auto 100px auto;
justify-content: stretch;
align-content: stretch;
}
2
3
4
5
6
那么,
- 当
justify-content取值为stretch时,设置内在尺寸的列网格轨道在内联轴方向会被拉伸,网格项目会沿着网格容器的内联轴方向填满(整个网格容器内联轴方向可用空间); - 当
align-content取值为stretch时,设置内在尺寸的行网格轨道在块轴方向被拉伸,网格项目会沿着网格容器块轴方向填满(整个网格容器块轴方向可用空间)。
Demo 地址: https://codepen.io/airen/full/GRGoEwQ
另外,当网格项目因合并网格单元格创建了一个隐式网格,并且隐式网格轨道尺寸为 auto 时,justify-cotent 和 align-content 取值为 stretch 时,同样会对网格项目进行拉伸:
.container {
inline-size: 500px;
block-size: 500px;
display: grid;
gap: 10px;
grid-template-columns: repeat(3, 100px);
grid-template-rows: repeat(3, 100px);
grid-auto-flow: dense;
justify-content: stretch;
align-content: stretch;
}
.item:nth-child(1) {
grid-row: 1 / span 2;
grid-column: 1 / span 2;
}
.item:nth-child(5) {
grid-column: 3 / span 2;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Demo 地址: https://codepen.io/airen/full/GRGoEwQ
在使用的时候,你还可以将 justify-content 和 align-content 简写成 place-content ,即:
place-content: <align-content> <justify-content>
当 place-content 只有一个值时,表示 align-content 和 justify-content 值相同,如果有两个值时,第一个值是 align-content ,第二个则是 justify-content :
.container {
place-content: center end;
/* 等同 */
align-content: center;
justify-content: end;
place-content: center;
/* 等同 */
align-content: center;
justify-content: center;
}
2
3
4
5
6
7
8
9
10
11
这样一来, Web 中又多了一种实现水平垂直居中的布局效果,即 place-content 属性的值设置为 center 。不过,使用 place-content 实现水平垂直居中,它有一个条件限制,网格容器中只有一个网格轨道,即 需要在网格容器中水平垂直居中的元素,它既是行网格轨道,也是列网格轨道 :
<div class="container">
<div class="item">我需要水平垂直居中</div>
</div>
.container {
display: grid;
place-content: center;
}
2
3
4
5
6
7
Demo 地址:https://codepen.io/airen/full/XWYmypr
用下图简单地总结一下,网格容器上设置 justify-content 或 align-content 属性的值,网格轨道的对齐方式如下:
Demo 地址: https://codepen.io/airen/full/RwJrXrQ
网格布局中,你可以同时使用多个对齐属性来控制网格中的对齐(网格项目或网格轨道),比如:
.container {
justify-content: space-evenly;
justify-items: center;
align-content: space-evenly;
align-items: center;
/* 等同于 */
place-content: space-evenly;
place-items: center;
}
2
3
4
5
6
7
8
9
10
正如你所看到的,由于可用于网格布局中的对齐属性很多种,如果你对网格布局中的对齐属性不是很了解的话,往往设置了对齐属性,却达不到预期的效果。这里有一个小技巧,你在网格布局中使用网格对齐相关的属性时,你需要做确认:
- 你是要对网格轨道设置对齐吗?如果是,使用
place-content属性;如果希望只控制网格轨道沿着网格容器块轴方向的对齐,则使用align-content;如果希望只控制网格轨道沿着内联轴方向的对齐,则使用justify-content。 - 你是要对所有网格项目设置对齐吗?如果是,使用
place-items属性;如果希望只控制网格项目沿着网格区域块轴方向对齐,则使用align-items;如果希望只控制网格项目沿着网格区域内联轴方向对齐,则使用justify-items。 - 你是要对单个网格项目设置对齐吗?如果是,使用
place-self属性;如果只希望控制单个网格项目沿着网格区域块轴方向对齐,则使用align-self;如果只希望控制单个网格项目沿着网格区域内联轴方向对齐,则使用justify-self。
比如下面这样的一个示列:
<div class="container">
<div class="item"></div>
<!-- 这里省略七个 item -->
<div class="item"></div>
</div>
2
3
4
5
.container {
inline-size: 100%;
max-width: 50vw;
margin: 0 auto;
aspect-ratio: 1;
display: grid;
gap: 1rem;
grid-template-columns: repeat(2, 120px auto);
grid-auto-rows: 120px auto;
grid-auto-flow: dense;
}
.item:nth-child(1) {
grid-row: span 2;
grid-column: span 2;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
使用上面的代码,构建了一个像下面这样的网格,其中网格项目一合并了两行两列:
目前为止,并没有显式地设置任何与对齐有关的属性。事实上,它相当于在网格容器上显式设置了 place-items 的值为 stretch ,即:
.container {
place-items: var(--align-items, stretch) var(--justify-items, stretch);
}
2
3
因为网格项目的 place-items (即 align-items 和 justify-items)的默认值是 stretch 。它也相当于在所有网格项目上设置了 place-self 的值为 stretch :
.container > * {
place-self: var(--align-self, stretch) var(--justify-self, stretch);
}
2
3
当你在网格容器 .container 显式设置 place-items 的值不是 stretch (非默认值)时,那么所有网格项目的对齐方式都会得到改变:
这个时候,要是你在单个网格项目上(比如网格项目一)显式设置了 place-self 的值为 stretch ,你会发现网格项目一在合并的网格区域的块轴和内联轴方向都会被拉伸,填满整个网格区域。即使是网格容器上显式设置了 place-items 的值为 center stretch :
.container {
place-items: center stretch;
}
.item:nth-child(1) {
place-self: stretch;
}
2
3
4
5
6
7
单个设置 place-self 的权重要大于在网格容器上设置的 place-items。正如你所看到的,网格项目一最终以自身 place-self 的值来控制对齐方式:
需要注意的是,place-content 的默认值是 start ,但这并不意味着网格容器默认就是 place-content 取值 start 的效果。就拿上面这个示例来说,在网格容器上设置 place-content 属性值为 start 前后的效果是不一样的:
也就是说,如果网格容器上未显式设置 place-content 时,并不会以默认的 place-content: start 来控制网格轨道的对齐 。
换句话说,只要在网格容器上显式设置了 place-content 属性(或它的子属性 align-content 或 justify-content)的值,就会改变设置值为 auto 的轨道尺寸,也会改变网格轨道之间的间距,但它不会改变网格项目的对齐方式。
你也可以简单的这么理解:
place-content改变网格的对齐方式和网格轨道之间的间距,但不会改变网格项目在网格区域的对齐方式;place-items和place-self会改变网格项目在网格区域的对齐方式,同时也会改变网格项目的尺寸,但不会改变网格轨道之间的间距;place-items用于网格容器,会改变所有网格项目;place-self用于网格项目,只会改变设置了该值的网格项目。
Demo 地址:codepen.io (opens new window)
# 网格项目的 margin:auto
通过前面课程的学习,你已经知道了在 Flex 项目中设置 margin 属性的值为 auto 时,可以达到 Flex 项目对齐的效果:
网格布局中,在网格项目上设置 margin 的值为 auto 时也能达到相似的效果。比如:
Demo 地址: https://codepen.io/airen/full/YzvqKgz
正如你所看到的,在网格布局中,你可以在网格项目上显式设置 margin: auto 实现水平垂直居中的效果:
.container {
display: grid;
}
.item {
grid-area: 1 / 1 / -1 / -1;
margin: auto;
}
2
3
4
5
6
7
8
Demo 地址: https://codepen.io/airen/full/xxzVxoV
除了在网格项目上显式设置 margin 的值为 auto 之外,也可以将其设置为 <length-percentage> 值,用来控制网格项目之间的间距。不过,它和网格容器上的 gap 属性还是有所区别的:
gap是用来设置网格轨道之间的间距;margin是用来设置网格项目外侧边缘和网格区域边缘之间的间距。
你会发现,网格项目上设置 margin 值时,网格项目会向里收缩!另外,网格布局中网格项目或网格轨道的对齐都是沿着网格容器的块轴方向或内联轴方向,所以使用 margin 值为 auto 达到对齐效果时,更建议采用相应的逻辑属性,比如:
magin-inline-start替代margin-left,相当于在网格项目上设置justify-self: end;margin-inline-end替代margin-right,相当于在网格项目上设置justify-self: start;margin-block-start替代margin-top,相当于在网格项目上设置align-self: end;margin-block-end替代margin-bottom,相当于在网格项目上设置align-self: start。
你也可以设置:
margin-inline的值为auto实现水平居中,等同于justify-self: center;margin-block的值为auto实现垂直居中,等同于align-self: center。
# 小结
网格布局中的对齐和 Flexbox 布局中的对齐有点相似,只不过网格布局中主要分为三种使用情景:
place-content(它的子属性align-content和justify-content)控制网格轨道在网格容器的块轴和内联轴方向的对齐;place-items(它的子属性align-items和justify-items)控制所有网格项目在网格区域的块轴和内联轴方向的对齐;place-self(它的子属性align-self和justify-self)控制单个网格项目在网格区域的块轴和内联轴方向的对齐。
它的 Flexbox 布局的 align-content 、justify-content 、alig``n-items 以及 align-self 还是有所差异的:
| 对齐属性 | Flexbox 布局中的对齐 | Grid 布局中的对齐 | 备注 |
|---|---|---|---|
align-content | Flex行在 Flexbox 容器侧轴方向的对齐 | 行网格轨道在网格容器的块轴方向的对齐 | Flex 行是指 Flexbox 容器上显式设置 flex-wrap 的值为 wrap 或 wrap-reverse 产生断行。每个 Flex 行都有主轴和侧轴方向 |
justify-content | Flex 项目在 Flex 容器主轴方向的对齐 | 列网格轨道在网格容器的内联轴方向的对齐 | |
place-content | place-content: <align-contetn> <justify-content> | ||
align-items | Flex 项目在 Flex 容器侧轴方向的对齐 | 所有网格项目在网格区域的块轴方向的对齐 | |
justify-items | 所有网格项目在网格区域的内联轴方向的对齐 | Flexbox 布局中不支持 justify-items | |
place-items | place-items: <align-items> <justify-items> | ||
align-self | 单个 Flex 项目在 Flex 容器侧轴方向的对齐 | 单个网格项目在网格区域的块轴方向的对齐 | |
justify-self | 单个网格项目在网格区域的内联轴方向的对齐 | Flexbox 布局中不支持 justify-self | |
place-self | place-self: <align-self> <justify-self> |
不管是 Flexbox 布局中的对齐还是网格布局中的对齐,它们都受 CSS 的书写模式或阅读模式的影响!
另外,网格布局中的网格项目上,也可以显式设置 margin 的值来达到单个网格项目对齐,这个和 Flexbox 布局中的 Flex 项目设置 margin: auto 是等同的:
| 属性:值 | Flexbox 布局 | Grid 布局 |
|---|---|---|
margin-left: auto | 如果 Flexbox 容器中只有一个 Flex 项目时,等同于在 Flex 容器上设置 justify-content 的值为 flex-end 或 end | 等同于在网格项目上设置 justify-self: end如果 Grid 容器中只有一个 Grid 项目时,等同于在网格容器上设置 justify-items: end 或 justify-content: end |
margin-right: auto | 如果 Flexbox 容器中只有一个 Flex 项目时,等同于在 Flex 容器上设置 justify-content 的值为 flex-start 或 start | 等同于在网格项目上设置 justify-self: start 如果 Grid 容器中只有一个 Grid 项目时,等同于在网格容器上设置 justify-items: start 或 justify-content: start |
margin-top: auto | 等同于在 Flex 项目上设置 align-self: end 或 align-self: flex-end 如果 Flexbox 容器中只有一个 Flex 项目时,等同于在 Flexbox 容器上设置 align-items 的值为 end 或 flex-end | 等同于在 Grid 项目上设置 align-self: end 如果 Grid 容器中只有一个 Grid 项目时,等同于在 Grid 容器上设置 align-items: end 或 align-content: end |
margin-bottom: auto | 等同于在 Flex 项目上设置 align-self: start 或 align-self: flex-start 如果 Flexbox 容器中只有一个 Flex 项目时,等同于在 Flexbox 容器上设置 align-items 的值为 start 或 flex-start | 等同于在 Grid 项目上设置 align-self: start 如果 Grid 容器中只有一个 Grid 项目时,等同于在 Grid 容器上设置 align-items: start 或 align-content: start |
不管是在 Flexbox 布局中还是 Grid 布局中,在 Flex 项目或 Grid 项目上设置:
magin-inline: auto可以实现水平居中;margin-block: auto可以实现垂直居中。
需要注意的是,因为 Flexbox 布局是一种一维布局,所以在 Flexbox 布局中没有 justify-items 和 justify-self 两个属性!
到这里,小册分了两节课分别介绍了 Flexbox 和 Grid 布局中的对齐。两个布局模块中都有相同的属性以及值,但所起的作用是略有差异的,但也有互通的。因此,在 CSS 规范中,将它们都纳入了 CSS Box Alignment 模块中。不过,在我们小册中不做展开性的阐述。因此,有关于对齐的部分我们就介绍到这里了。