參考資料:https://www.bilibili.com/video/BV1Bk4y197xm
一、Grid布局簡介
從某種程度上說,grid布局是flex布局的升級版,主要用於元素在平面上的布局,例如我當前博客皮膚主頁上每個隨筆卡片的排布:

bilibili首頁上圖片鏈接的排版:

可以看出,grid布局往往用於在平面上排列元素,而且可以達到不錯的效果。
這也是grid布局和flex布局的主要差異,即:
- flex布局一般用於一個維度排布元素項(item),例如橫向或縱向一個方向排布
- grid布局主要用於在整個平面上(二維)對元素項進行排布,例如單子商城的各個商品項,文章管理系統的各個文章,使用grid布局可以達到非常好的瀏覽效果。
二、Grid布局的一些概念
和flex布局類似,grid布局也涉及容器元素和子元素,我們可能需要在兩種元素內都設置相應的css屬性才能得到希望的結果。
grid布局中的基本概念如下圖所示:

要啟用grid布局,和flex布局一樣,只需要修改容器元素的display
css屬性為grid
即可,如:
.grid-container {
display: grid;
}
三、 容器元素屬性
1. grid-template-*
1.1 網格行和列的設置
首先是grid-template-columns
,它可以用於設置當前排列元素有多少列以及每列的寬度,例如設置:
.grid-container {
display: grid;
grid-template-columns: 100px 100px 100px;
...
}
這樣設置代表排列元素為三列,每列的寬度為100px,效果如下:

同理,我們也可以設置排列元素的行數以及每一行的高度:
.grid-container {
...
grid-template-rows: 100px 100px 100px 100px;
}

調試工具下的效果:

1.2 repeat的使用
像剛才那樣設置元素的行列可能會遇到一種麻煩的情況,例如如果列數有10列,那么我們則需要寫10次列的寬度,此時我們就可以使用repeat
寫法進行簡化,即:
.grid-container {
grid-template-columns: repeat(3, 100px); /* => 100px 100px 100px */
}
第一個參數是數量,第二個參數是大小。
此外,repeat
里的第一個參數也可以設置為auto-fill
,這樣子元素就會根據父元素的寬度大小進行自適應排列了,例如:
- 容器寬度為600px
- 容器寬度為400px
1.3 使用fr
fr可以方便地表示比例關系,和flex布局中給子元素設置flex屬性表示自己的占比類似。
例如在這里希望容器分成三列,並且每列等分容器的寬度,那么我們可以這樣寫:
.grid-container {
grid-template-columns: repeat(3, 1fr);
}
這代表着每行的每個元素都占據一份的剩余空間,因此可以實現三等分的效果:

我們也可以自定義比例,例如:
.grid-container {
grid-template-columns: 1fr 2fr 3fr;
}

可以看出,各列的寬度變成了1:2:3
。
1.4 auto關鍵字
例子如下:
.grid-container {
grid-template-columns: 100px auto 100px;
}
此時代表左右兩列各占用100px寬度,而中間則自動填充滿,這樣既是我們前面使用flex布局所得到的三欄布局:

2. row-gap, column-gap
顯而易見,這兩個屬性都是用於設置子元素之間間距的大小的
- row-gap設置行間距
- column-gap設置列間距
例如設置行間距:
.grid-container {
...
row-gap: 20px;
}

列間距是類似的,這里不贅述了。
此外還可以直接使用gap
來簡化兩個間距的設置:
.grid-container {
...
gap: 20px;
}

3. grid-auto-flow
這個屬性主要用於設置元素是以行優先還是列優先進行排列的,默認為行優先,因此我們進行這樣的修改:
.grid-container {
grid-auto-flow: column;
}
效果如下:

dense關鍵字
例如一些這種情況:

這里1號和2號元素的寬度都比較大,2號元素無法放在1號元素的右邊,因此1號元素右邊就出現了一個空位,而此時我們希望3號元素能夠向上占據這個空位進行緊密的排列,此時我們就可以在grid-auto-flow
屬性后添加dense
關鍵字:
.grid-container {
grid-auto-flow: row dense;
}

可以看到,此時完成了我們緊密排列的需求。
4. items對齊
4.1 justify-items
這個屬性用於設置子元素元素在網格內的水平方向上的對齊。

這個屬性即用於設置子元素在規定的網格中是以什么樣的方式進行對齊的,具體效果如上圖所示,其默認值為stretch
(拉伸),這也就是為什么我們看到子元素占滿了各自的網格。
4.2 align-items
同理,這個屬性用於設置子元素元素在網格內的垂直方向上的對齊,這里不展開了。
4.3 place-items
這個屬性是上面兩個屬性的簡寫,即:
.grid-container {
place-items: center center; /* => justify-items:center; align-items: center; */
}
5. content對齊

這里的“整個內容區域”指的是前面紅色概念圖中的紅色方框區域,並不是值整個容器,例如原來的例子中的content為下圖綠色邊框包圍的最外圍區域:

因此,這個屬性是用於設置content關於整個容器的對齊關系的。
因而我們可以設置整個部分垂直居中和水平居中:
.grid-container {
...
justify-content: center;
align-content: center;
}

其他的對齊方式和flex中展現的類似,在此不再贅述。
6. grid-auto-columns/grid-auto-rows
這兩個屬性分別用於設置多出來的項目的寬和高:

7. 定義區域
使用方式如下案例所示:
.grid-container {
grid-template-areas:
'a b b'
'a c d'
'a e f';
}
這里區域的命名可以是任意的英文單詞,上面代碼所對應的實際區域為:

這里只是定義區域,在子元素屬性上進行相應的設置可以使該子元素占據某個區域。
四、item(子元素)屬性
1. grid-column,grid-row

簡寫:
.item {
grid-column: 1 / 3;
/*
=> grid-column-start: 1;
grid-column-end: 3;
*/
}
另一種寫法:使用span
.item {
grid-column-start: span 2;
}
代碼的效果和上面相同。
2. grid-area
如上所述,使用這個屬性可以使某個子元素占據在容器元素屬性中定義的區域:
.item-1 {
grid-area: a;
}

可以看到,1號元素占據了a區域。
此外,grid-area
還可以用於簡寫上面的item位置設置:

3. 定義單個子元素在網格的對齊方式
