CSS 網格布局除了提供定義網格和放置網格項目的相關屬性之外,也提供了一些控制對齊方式的屬性。這些控制對齊方式的屬性,和 Flexbox 布局中的對齊屬性 justify-*
、align-*
、*-items
、*-content
、 *-self
等是相似的:
在網格布局中可以用它們來控制網格項目在內聯軸(Inline Axis)和塊軸(Block Axis)的對齊方式;也可以用來控制網格軌道在內聯軸(Inline Axis)和塊軸(Block Axis)的對齊方式。
接下來,在這節課程中,我將演示網格布局中的對齊方式是如何工作的,你會發現很多屬性和值與 Flexbox 布局中的用法是類似的(Flexbox 布局對齊方式請參閱讀前面課程:《04 | Flexbox 布局中的對齊方式 》)。不過,網格布局是二維的,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;
}
上面的代碼構建了一個四行十列(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);
}
正如上圖所示:
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);
}
當然,你也可以在單個網格項目上顯式設置 align-self
的值:
.item:nth-child(1) {align-self: start;
}.item:nth-child(2) {align-self: end;
}.item:nth-child(3) {align-self: center;
}
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;
}
上面這個示例,網格項目一在塊軸方向始終是是垂直居中的,因為它顯式設置了 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);
}
正如上圖所示:
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);
}
你也可以根據需要,在網格項目上單獨設置 justify-self
屬性的值,控制單獨網格項目在內聯軸方向的對齊:
.item:nth-child(1) {justify-self: start;
}.item:nth-child(2) {justify-self: center;
}.item:nth-child(3) {justify-self: end;
}
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;
}
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>
當 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;
}
注意,
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;
}
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;
}
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)
}
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);
}
可以像 Flexbox 布局中的 justify-content
和 align-content
一樣,將剩余空間分配到網格軌道之間。
在網格容器上將 align-content
設置不同值:
.container {align-content: var(--align-content, start);
}
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;
}
Demo 地址: https://codepen.io/airen/full/poKgeMR
也就是說,當網格容器沒有剩余空間時,align-content
各值的效果都相同,即等同于 align-content
的 start
(默認值效果) 。
既然網格容器有剩余空間,也就有可能會有不足空間出現,比如將示例中的行網格軌道尺寸設置為:
.container {grid-template-rows: 70% 120px 120px;
}
網格項目溢出網格容器:
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;
}
Demo 地址:https://codepen.io/airen/full/OJEMmxN
上面看到的都是行網格軌道在網格容器塊軸方向的對齊方式(分配網格容器塊軸方向剩余空間)。接下來在前面的示例基礎上,將 align-content
換成 justify-content
。
.container {justify-content: var(--justify-content, start);
}
不難發現,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;
}
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;
}
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;
}
那么,
- 當
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;
}
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;
}
這樣一來, Web 中又多了一種實現水平垂直居中的布局效果,即 place-content
屬性的值設置為 center
。不過,使用 place-content
實現水平垂直居中,它有一個條件限制,網格容器中只有一個網格軌道,即 需要在網格容器中水平垂直居中的元素,它既是行網格軌道,也是列網格軌道 :
<div class="container"><div class="item">我需要水平垂直居中</div>
</div>
.container {display: grid;place-content: center;
}
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;
}
正如你所看到的,由于可用于網格布局中的對齊屬性很多種,如果你對網格布局中的對齊屬性不是很了解的話,往往設置了對齊屬性,卻達不到預期的效果。這里有一個小技巧,你在網格布局中使用網格對齊相關的屬性時,你需要做確認:
- 你是要對網格軌道設置對齊嗎?如果是,使用
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>
.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;
}
使用上面的代碼,構建了一個像下面這樣的網格,其中網格項目一合并了兩行兩列:
目前為止,并沒有顯式地設置任何與對齊有關的屬性。事實上,它相當于在網格容器上顯式設置了 place-items
的值為 stretch
,即:
.container {place-items: var(--align-items, stretch) var(--justify-items, stretch);
}
因為網格項目的 place-items
(即 align-items
和 justify-items
)的默認值是 stretch
。它也相當于在所有網格項目上設置了 place-self
的值為 stretch
:
.container > * {place-self: var(--align-self, stretch) var(--justify-self, stretch);
}
當你在網格容器 .container
顯式設置 place-items
的值不是 stretch
(非默認值)時,那么所有網格項目的對齊方式都會得到改變:
這個時候,要是你在單個網格項目上(比如網格項目一)顯式設置了 place-self
的值為 stretch
,你會發現網格項目一在合并的網格區域的塊軸和內聯軸方向都會被拉伸,填滿整個網格區域。即使是網格容器上顯式設置了 place-items
的值為 center stretch
:
.container {place-items: center stretch;
}.item:nth-child(1) {place-self: stretch;
}
單個設置 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
網格項目的 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;
}
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 模塊中。不過,在我們小冊中不做展開性的闡述。因此,有關于對齊的部分我們就介紹到這里了。