整理 Grid 的排版與範例
前言
在 Youtube 看 Amos 大大 解說 Grid 的各種屬性及運用,所以將一些使用方式及技巧做個紀錄。
CSS Grid
繼 Flexbox 之後,另一新品種的排版方式,
而主要排版可選「格子」或「線條」二種方式去分配區塊。
「格」的概念
定義好共有「幾列幾欄」後,再依照有幾個區塊,分別要放置哪個地方。
分配放置的結果,如下所示
父層
grid-template-rows
:設定幾 列grid-template-columns
:設定幾 欄grid-template-areas
:分配各區塊佔據的位置
子層
grid-area
:佔據的名稱
範例
1 | <div class="container"> |
1 | .container { |
範例程式:JSBin
grid-template-areas 須為連續區塊
在分配區塊的位置時,須為連續矩形區塊,不可有「交叉、L 形」之類的分配。
正確
錯誤
B3區塊這樣設定的話,就會造成 Grid 壞掉。
新單位 fr(fractional)
原本我們分配rows
或columns
時,單位都是使用px
、%
…等,
而 Grid 有提供一個新單位fr
, 他的概念就像「幾分之幾」一樣,
下列用範例說明解釋
範例說明
1 | grid-template-rows: 1fr 1fr 2fr 1fr; |
先將全部的 fr 加總,所以共有 5fr,然後上例共分成四個區塊,
所以分別佔據的面積就為 1/5
、1/5
、2/5
、1/5
repeat
如果分配的區塊都相同或者有一定的規則時,這樣我們就可以用 repeat 來重覆定義。
1 | grid-template-rows: repeat(4, 1fr); |
也可以多個。
1 | grid-template-rows: repeat(2, 1fr 2fr); |
grid-gap 格線
簡單來說,就是設定每個區塊上下左右之間,是否有空隙,
另外如果有設定grid-gap
時,整個區塊的空間會先分配給grid-gap
後,
剩餘的空間,再給fr
去做切割使用。
語法
grid-gap: 列row / 欄column;
也可分別設定的,
grid-row-gap: 列row;
grid-column-gap: 欄column;
範例
1 | <div class="grid-container"> |
1 | .grid-container { |
範例程式:JSBin
「線」的概念
我們一樣切割為「四欄四列」,而「面的概念」是用佔據第幾個區塊來分配,
不過「線」的話,就是用「起始線/終點線」來規劃佔據的範圍到哪裡,
再說三次,線的概念為
起始線/終點線起始線/終點線
起始線/終點線
範例
用上面「面的範例」來修改,註解掉的地方為「面的寫法」,
改用「線的寫法」,來呈現一樣結果。
1 | .container { |
範例程式:JSBin
線的分配可為「負值」
線的分配設定值為:起始線/終點線,不過裡面的值可為「負數」,
代表從尾段往前計算線條位置。
範例
1 | .box1 { |
範例程式:JSBin
span 的用法
前面我們說「線」的分配設定值為:起始線/終點線,其實也可以配合「span」來使用。
不過使用span
時,要特別注意二點
span
的值,只能 正數span
的方向,都是 由左至右、由上而下
不過第二點比較容易踩雷,所以再說三次
由左至右、由上而下由左至右、由上而下
由左至右、由上而下
範例
以此圖來說,我想要 A、B 二區塊,從上而下全部佔滿,
這時除了使用 起始線/終點線 的寫法外,
我可以使用 span
來表示要佔據幾格。
1 | .box1 { |
從上例來看 .box2
的 grid-row: 1/ span 4;
,
就是從 起始線 1 的位置 開始佔據 4 格 的空間。
範例程式:JSBin
特殊分配法
介紹完「面與線」的概念後,再來我們先來個簡單又特別的範例,
範例
下例切割為「八列八欄」,共有 ABCD 區塊要分配,我們要排成一個斜線的形狀。
1 | <div class="container"> |
1 | .container { |
範例程式:JSBin
可「重疊」分配
再用上例來修改,如果想要 C 的部份區塊要蓋在 B 區塊上面,只要將二者分配的值,有交錯即可。
1 | // ...略 |
範例程式:JSBin
如果想要換成 B 蓋在 C 上面的話,就可以使用
position
和 z-index
配合使用,不過在 Grid 裡,可以直接使用
z-index
即可。grid-auto-* 自動切割欄列
1 | // 固定分配 |
再來我們來說說,grid-template-*
與 grid-auto-*
之間差異點,
就是 grid-auto-*
會自動計算你使用的正整數最大值後,自動用最大值去切割區塊,
這樣可能還不是很清楚,我們用範例來說明:
範例
1 | .container { |
從上例來看的話,我們先看 rows
的部份,
.box1
:grid-row: 1/10;
.box2
:grid-row: 3/5;
上述row
裡面最大正整數值為:10,
不過要注意 10 是終點線,所以要扣掉 1,共切了 9 格;
而 columns
的部份規則也是一樣,
.box1
:grid-column: 1/2;
.box2
:grid-column: 1/8;
上述columns
裡面最大正整數值為:8,
所以 8 - 1 = 7 ,共切了 7 格。
範例程式:JSBin
minmax()
指定最小格線及最大格線。
範例:
1 | <div class="grid"> |
1 | * { |
說明 minmax(160px, 1fr)
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
簡單說明一下,上述程式碼
auto-fill
就是自動填滿,那用 minmax(160px, 1fr)
填滿是什麼意思呢!
單單從 minmax(160px, 1fr)
這程式碼來描述的話,
最小值就是 160px
,而最大值是 1fr
??
那1fr
又代表多少呢?
讓我再用簡單例子來說明(給自己聽),
因為我本身設定最小值為160px
,所以當我一列若要可以塞下第二個 div 的話,
我最少也要有 160px*2=320px
的寬度,才能塞得下第二個 div,
所以當一列的寬度在 160px~319px
時,只會有一個 div,
並且這一個 div 會在160px~319px
之間,自動幫我伸縮它的寬度,
但當我一列的寬度到達 320px
寬度時,它就會塞入第二個 div 在同一列上,
所以我大膽假設minmax(160px, 1fr)
的1fr
,
就是取 最小值 * 2 - 1px 吧!
範例:
寬度:320px 時,一列可放 2 張圖片
寬度:480px 時,一列可放 3 張圖片
範例程式:JSBin
對齊方式
- 水平軸對齊
- justify-content:整個 grid 範圍
- justify-items:所有格子 統一設定
- justify-self:一個格式 單獨設定
- 垂直軸對齊
- align-content:整個 grid 範圍
- align-items:所有格子 統一設定
- align-self:一個格式 單獨設定