CSS Grid 格線佈局

Flexbox 的出現讓很多人捨棄了舊有的排版方式,大多數的時候我也還是使用 Flexbox,但最近遇到的需求版型比較複雜,於是開始學習 Grid。

我認為 Grid 很適合用在 Dashboard 的排版,比如:

不是說 Flexbox 無法做到這個版型,而是用 Grid 來排真的比較快又簡單很多。

實用輔助工具 - Google Chrome 的格線預覽

開始前先來介紹實用的 Google Chrome 小工具。有一個版型長這樣:

藉由 F12 開發者工具右上角的功能,可以看到原本的格線佈局:

開始使用

先讓包在最外層的父元素變成 Grid Container:

1
2
3
.wrapper {
display: grid;
}

設定 Grid Container

要設定 Grid Container,最基本會用到 grid-template-rows / grid-template-columns 這兩個屬性。

grid-template-rows 是縱軸,grid-template-columns 則是橫軸

明確定義寬高

簡單來說就是使用 px、%、vw 或 vh 去設定寬高:

1
2
3
4
.wrapper {
display: grid;
grid-template-columns: 200px 200px 200px;
}

簡易示範

一起來切個常見的 layout~

HTML

1
2
3
4
5
6
<div class="wrapper">
<div>menu</div>
<div>nav</div>
<div>sidebar</div>
<div>content</div>
</div>

CSS

1
2
3
4
5
6
7
8
9
.wrapper {
display: grid;
grid-template-rows: 60px 600px;
grid-template-columns: 200px 1000px;
}

.wrapper div {
border: solid 1px;
}

See the Pen Grid 01 by Priscilla Lin (@Priscilla_Lin) on CodePen.


用等分決定寬高

這時候就是使用只有在 Grid 出現的格線單位:fr。1fr 是一等分的意思,2fr 就是兩等分,以此類推。

1
2
3
4
5
.wrapper {
display: grid;
grid-template-rows: 2fr 1fr 1fr;
grid-template-columns: 2fr 1fr 1fr;
}

也可以和自定義的數值混用,這樣的話就會扣掉固定數值,剩下的寬(高)再平分。

1
2
3
4
5
.wrapper {
display: grid;
grid-template-rows: 2fr 1fr;
grid-template-columns: 200px 1fr 1fr;
}

設定成 Grid Container 後,寬度預設是滿版,所以 columns 會以 100 vw 下去切成好幾等分。

但 rows 就不同了,它會把子元素的高度當成依據,去計算 1fr 的高度是多少。如果同一行中有不同的高度,則以高度最大的那個子元素為準。

See the Pen Grid 02 by Priscilla Lin (@Priscilla_Lin) on CodePen.


repeat

repeat(格數, 格寬/高)

如果 Row 或 Column 的寬度是相同的,而且需要好幾格,這時候就可以用 repeat

1
2
3
4
5
.wrapper {
display: grid;
grid-template-rows: repeat(10, 50px);
grid-template-columns: repeat(10, 1fr);
}

See the Pen Grid repeat by Priscilla Lin (@Priscilla_Lin) on CodePen.


minmax

minmax(最小值, 最大值)

minmax 可以指定最小值和最大值,在設計響應式頁面很方便:

1
2
3
4
5
.wrapper {
display: grid;
grid-template-rows: minmax(50px, 100px);
grid-template-columns: minmax(50px, 100px);
}

以上面的例子來看,一般 PC 的情況下 columns 會呈現 100px,隨著頁面寬度變化慢慢縮小,如果擠到不能再擠了,就會維持最小寬度 50px。rows 也是一樣的原理。

See the Pen Grid minmax by Priscilla Lin (@Priscilla_Lin) on CodePen.


客製化區塊

要做到客製化區塊,可以靠這兩種設定方式做到:

grid-template-areas

grid-template-areas 可以單獨定義每一格,但有幾點必須注意:

  • 區塊如果要合併,必須要連續,像ㄇ形或L型是不行的
  • 定義完後,子元素的 class 必須加入 grid-area 指定區塊
  • 使用 . 可以留空區塊

HTML

1
2
3
4
5
6
7
<div class="wrapper">
<div class="nav">nav</div>
<div class="sidebar">sidebar</div>
<div class="content-01">content-01</div>
<div class="content-02">content-02</div>
<div class="content-03">content-03</div>
</div>

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
.wrapper {
display: grid;
grid-template-rows: 60px 300px 300px;
grid-template-columns: 200px 500px 500px;
grid-template-areas:
"nav nav nav"
"sidebar content-01 content-02"
"sidebar content-03 content-04";

/* (x) 倒L型 nav
* grid-template-areas:
* "nav nav nav"
* "nav content-01 content-02"
* "nav content-03 content-04";
*/
}

.wrapper div {
border: solid 1px;
}

.nav {
grid-area: nav;
}

.sidebar {
grid-area: sidebar;
}

.content-01 {
grid-area: content-01;
}

.content-02 {
grid-area: content-02;
}

.content-03 {
grid-area: content-03;
}

See the Pen Grid grid-template-areas by Priscilla Lin (@Priscilla_Lin) on CodePen.


各個 Class 分別指定

這邊也分成兩種方式:

  • grid-[row/column]-start / grid-[row/column]-end
1
2
3
4
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: 2;
grid-column-end: 3;
  • grid-[row/column]: start / end
1
2
grid-row: 1 / 2;
grid-column: 2 / 3;

數字的部分是這樣數過去,由左而右,由上到下,從 1 開始數:

這邊有兩個特殊用法:

  • span:跨越幾個區塊
1
grid-row: 1 / span 3;
  • auto:設定 auto 通常為 start 值 +1
1
grid-row: 1 / auto;

CSS (註解和未註解的部分是同樣效果不同寫法。HTML 沿用上個範例)

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
.wrapper {
display: grid;
grid-template-rows: 60px 300px 300px;
grid-template-columns: 200px 500px 500px;
}

.wrapper div {
border: solid 1px;
}

/* -------------------- */

/* .nav {
grid-row-start: 1;
grid-row-end: 2;
grid-column-start: 1;
grid-column-end: span 3;
} */

.nav {
grid-row: 1 / 2;
grid-column: 1 / span 3;
}

/* -------------------- */

/* .sidebar {
grid-row-start: 2;
grid-row-end: 4;
grid-column-start: 1;
grid-column-end: 2;
} */

.sidebar {
grid-row: 2 / 4;
grid-column: 1 / 2;
}

/* -------------------- */

/* .content-01 {
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 2;
grid-column-end: 3;
} */

.content-01 {
grid-row: 2 / 3;
grid-column: 2 / 3;
}

/* -------------------- */

/* .content-02 {
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 3;
grid-column-end: 4;
} */

.content-02 {
grid-row: 2 / 3;
grid-column: 3 / 4;
}

/* -------------------- */

/* .content-03 {
grid-row-start: 3;
grid-row-end: 4;
grid-column-start: 3;
grid-column-end: 4;
} */

.content-03 {
grid-row: 3 / 4;
grid-column: 3 / 4;
}

See the Pen Grid assign block in child by Priscilla Lin (@Priscilla_Lin) on CodePen.


grid-auto-rows / grid-auto-columns

如果只是想要簡單設定 rows 或 columns,可以用 grid-auto-rowsgrid-auto-columns

grid-auto-rows

1
2
3
4
5
6
.wrapper {
display: grid;
width: 50vw;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: 100px;
}

See the Pen Grid auto rows by Priscilla Lin (@Priscilla_Lin) on CodePen.

grid-auto-columns

1
2
3
4
5
.wrapper {
display: grid;
height: 500px;
grid-auto-columns: 200px;
}

See the Pen Grid auto columns by Priscilla Lin (@Priscilla_Lin) on CodePen.


gap

gap 各區塊之間的間距,可以一起設定,也可以 rows 和 columns 分開設定。

一起設定 gap

1
2
3
4
5
6
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-gap: 10px;
}

分開設定 gap

1
2
3
4
5
6
7
8
.wrapper {
display: grid;
width: 50vw;
grid-template-columns: 1fr 1fr 1fr;
grid-auto-rows: 100px;
grid-row-gap: 10px;
grid-column-gap: 0px;
}

See the Pen Grid gap by Priscilla Lin (@Priscilla_Lin) on CodePen.


Grid 對不同瀏覽器的支援

Grid 目前的支援不像 Flexbox 那麼好,不過主流瀏覽器幾乎都有支援。

CSS Grid Layout (level 1) | Can I use… Support tables for HTML5, CSS3, etc

文章結束囉~

如果我的文章對你有幫助,可以幫我拍個手,感謝支持!