(3) CSS基礎篇 Grid

Grid 排版

Grid和flex一樣是用來排版的屬性,flex以單軸為主來排版,Grid則能夠同時設定兩個方向(欄和列),能夠快速建立網頁布局。

Grid的屬性可以分成外部屬性和內部屬性,以下分別介紹。

外部容器(父層)

以下介紹可以在父層設定的屬性

display

在父層容器設定 display: grid,讓父層是 gird 容器。

  • grid – 設定 block-level的 grid
  • inline-grid – 設定 inline-level的 grid
1
2
3
.container {
display: grid | inline-grid;
}

grid-template-columns grid-template-rows

設定好 display:grid後,可以用grid template 來定義版型的結構,分別設定column(欄),和列(row)來排列格線,grid-template-columns 定義水平方向的空間,grid-template-rows 定義垂直方向的空間

grid
圖片來源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.container {
grid-template-columns: ... ...;
/* e.g.
1fr 1fr
minmax(10px, 1fr) 3fr
repeat(5, 1fr)
50px auto 100px 1fr
*/
grid-template-rows: ... ...;
/* e.g.
min-content 1fr min-content
100px 1fr max-content
*/
}

設定單位可以使用彈性的長度、百分比
或用fr (等分),如下例會將父層寬度扣掉50px後,分成三等份到三欄裡。

1
2
3
.container {
grid-template-columns: 1fr 50px 1fr 1fr;
}

如果有重複一樣寬度的欄位,則可以用repeat設定。

1
repeat(欄位數量, 寬度)

grid-template-areas

grid-template-areas可以透過將每個欄位命名,將內容作分配。

在父層設定 grid-template-areas,可設定的值有:

  • [欄位名稱] : 設定該欄位名稱。
  • . 設定 . 代表是空的欄位。
  • none: 代表欄位未定義。

在子層則設定 grid-area 決定內容要放到哪個欄位。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
.item-a {
grid-area: header;
}
.item-b {
grid-area: main;
}
.item-c {
grid-area: sidebar;
}
.item-d {
grid-area: footer;
}

.container {
display: grid;
grid-template-columns: 50px 50px 50px 50px;
grid-template-rows: auto;
grid-template-areas:
"header header header header"
"main main . sidebar"
"footer footer footer footer";
}

grid-area
圖片來源

grid-gap, grid-column-gap, grid-row-gap

設定水平與垂直的欄位間隔

1
2
3
column-gap: { column-gap };  //設定每欄的間隔
row-gap: { row-gap }; //設定每列的間隔
gap: { row-gap } { column-gap }; // 同時設定欄和列的間隔
1
2
3
4
5
6
.container {
grid-template-columns: 100px 50px 100px;
grid-template-rows: 80px auto 80px;
column-gap: 10px;
row-gap: 15px;
}

justify-items

justify-items 可以設定子元素水平對齊格子的方式,可設定的值有:

  • start: 對齊開頭
  • end: 對齊末端
  • center: 對齊中間
  • stretch: 填滿格子(預設值)
1
2
3
.container {
justify-items: start;
}

justify-items: start

align-items

align-items 可以設定子元素垂直對齊格子的方式,可設定的值有:

  • start: 對齊頂端
  • end: 對齊底部
  • center: 對齊中間
  • stretch: 填滿格子(預設值)
1
2
3
.container {
align-items: center;
}

align-items: center

place-items

place-items 能同時設定 justify-items跟align-items

1
place-items: <align-items> / <justify-items>

第一個值設定 align-items,第二個值設定 justify-items。如果只設一個值,則會同時套用到 justify-items跟align-items。

1
2
3
4
.center {
display: grid;
place-items: center; // 快速將內容置中於格子內
}

justify-content、align-content

有時候你的格子尺寸可能會小於父層grid容器,此時可以用 justify-content 同時調整所有子元素的水平對齊,align-content 同時調整所有子元素的垂直對齊

可設定的值:

  • start: 對齊開頭
  • end: 對齊末端
  • center: 對齊中間
  • stretch: 填滿格子(預設值)
  • space-around: 平均分配寬度和間距
  • space-between: 平均分配寬度,第一項和最後一項貼齊邊緣
1
2
3
.container {
justify-content: end;
}

justify-content: end

1
2
3
.container {
align-content: space-around;
}

align-content: space-around

grid-auto-columns 、 grid-auto-rows

當我們的grid-items數量超過我們設定的格線,或是將元素指定到格線以外時,會自動產生格線。
如下我們設定一個 2 x 2的格線。

1
2
3
4
.container {
grid-template-columns: 60px 60px;
grid-template-rows: 90px 90px;
}

但子元素設定的區域超過格線內,會自動產生格線。

1
2
3
4
5
6
7
8
.item-a {
grid-column: 1 / 2;
grid-row: 2 / 3;
}
.item-b {
grid-column: 5 / 6;
grid-row: 2 / 3;
}

gird

此時可以設定 grid-auto-columns | grid-auto-rows 來指定自動產生的格線寬度。等於是設定格線寬度或高度的預設值,當格線沒有被 grid-template-columns 設定寬度時,就套用 grid-auto-columns的值。

1
2
3
.container {
grid-auto-columns: 60px;
}

grid-auto-flow

當有grid-item沒有被指定位置時,gird會自動排列這些grid-item,排列方式如下:

  • row: 水平排列 (預設值)
  • column: 垂直排列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.container {
display: grid;
grid-template-columns: 60px 60px 60px 60px 60px;
grid-template-rows: 30px 30px;
grid-auto-flow: row;
}
.item-a {
grid-column: 1;
grid-row: 1 / 3;
}
.item-e {
grid-column: 5;
grid-row: 1 / 3;
}

水平排列

item-b、item-c、item-d 因為沒有指定位置,自動依照grid-auto-flow水平排列

垂直排列

item-b、item-c、item-d 因為沒有指定位置,自動依照grid-auto-flow垂直排列

內部元素(子層)

以下介紹可以在內部元素設定的屬性

grid-column-start, grid-column-end, grid-row-start, grid-row-end

物件所佔的空間位置,Column 及 Row 所到的起始點及終點

1
2
3
4
5
6
.item {
grid-column-start: <number> | <name> | span <number> | span <name> | auto;
grid-column-end: <number> | <name> | span <number> | span <name> | auto;
grid-row-start: <number> | <name> | span <number> | span <name> | auto;
grid-row-end: <number> | <name> | span <number> | span <name> | auto;
}
  • number : 用數字表示 物件 所在的線。
  • span number - 物件會橫跨的欄位數
  • span name - 物件所在的 grid 名稱
  • auto - 自動
1
2
3
4
5
.item-a {
grid-row-start: 3; /* 物件起始線 */
grid-column-end: span 4; /* 終點線 = 物件所佔的空間數 */
grid-row-end: auto; // 不設定終點線
}

grid-column 、 grid-row

上面屬性的縮寫,使用斜線 (/) 隔開屬性。

1
2
3
4
.item {
grid-column: <start-line> / <end-line> | <start-line> / span <value>;
grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}
  • start-line: 開始的格線
  • end-line : 結束的格線
  • span value: 指定橫跨的欄位數
1
2
3
4
.item-c {
grid-column: 3 / span 2;
grid-row: third-line / 4;
}

grid-column

justify-self

指定單一格子內的grid-item水平對齊的方式,可設定的值如下:

1
2
3
.item {
justify-self: start | end | center | stretch(預設值);
}

範例:

1
2
3
.item-a {
justify-self: start;
}

justify-self

align-self

指定單一格子內的grid-item垂直對齊的方式,可設定的值如下:

1
2
3
.item {
align-self: start | end | center | stretch;
}

範例:

1
2
3
.item-a {
align-self: end;
}

align-self

place-self

是 align-self跟justify-self的縮寫,用法如下:

1
place-self : <align-self> / <justify-self> 

第一個值設定 align-self,第二個值設定justify-self。如果只設定一個值,則會同時套用到align-self跟justify-self。

1
2
3
.item-a {
place-self: center;
}

center

1
2
3
.item-a {
place-self: center stretch;
}

place-self

特殊單位與函式

fr 單位

在grid裡,可以用 fr 作為單位,1fr指的是 1等分。

1
grid-template-columns: 1fr 3fr;

上面我們設定的兩欄就分別代表 25% 和 75% 的寬度。

fr 也可以搭配其他單位使用

1
grid-template-columns: 50px min-content 1fr;

關鍵字

當我們在設定欄位長寬時,可以用 px 、% 、rem 等等,也可以使用關鍵字設定。

  • min-content: 指的是內容的最小尺寸
  • max-content: 指的是內容的最大尺寸

min-content

假設有一個grid-item是一段句子:

  • min-content: 句子裡最長的字的寬度。
  • max-content: 完整句子的寬度。

特殊函式

  • minmax(最小寬度, 最大寬度)

使用 minmax 可以同時設定欄位的最小和最大寬度

1
grid-template-columns: minmax(100px, 1fr) 3fr; 
  • repeat(欄位數量, 欄位寬度)

當要設定的欄位寬度都一樣時,可以用 repeat方法來設定

1
2
3
4
5
6
7
8
9
10
grid-template-columns:
1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;

/* easier: */
grid-template-columns:
repeat(8, 1fr);

/* especially when: */
grid-template-columns:
repeat(8, minmax(10px, 1fr));

在使用 repeat() 時,如果不確定自己要的重複次數,可以使用 auto-fill 和 autofit 讓重複的網格持續填滿。

1
2
3
4
5
6
.grid {
display: grid;
width: 500px;
gird-template-columns: repeat(auto-fill, 100px);
grid-template-rows: repeat(3, 50px)
}

如上例,因為容器寬度是500px, 設定auto-fill 會產生 5 * 3的網格。

至於 auto-fill 和 auto-fit的差異在:

  • auto-fill: 盡量產生重複的欄位。
  • auto-fit: 盡量產生重複的欄位,但多的格子會被設為0px,折疊起來。

詳細解說文章看這