因為已經學過flex,順手筆記一下剛好看到 Grid 版面配置。
先回想一下Flex的版面配置, Flex 只能決定容器(container)裡面物件的定位方向是根據 row 還是 column。
不同於 Flex 是只能處理一維定位的版面配置屬性,Grid 則如下圖所示,可以處理二維定位的版面配置屬性,也就是可以同時將一個容器內的row、column排列方式設定好。
簡之,Grid 就是在頁面容器 column 和 row 方向上定義一系列縱橫交錯的線來排版容器內物件的網格系統。
這裡擷取在CSS Working Group Editor Drafts的Grid應用:
從這張圖可以發現,如果要用 div
和 flex
屬性排版,頁面的上半部就可能要如下圖在紅色(row)和藍色(column)部分設定兩次 flex
:
使用Grid的方式就是:在一個容器(wrapper)設定以 grid 去排列容器以內的物件。
簡要列點一下Grid的排版步驟:
- 決定容器: 設定一個容器(wrapper)排版容器內的物件,容器要指定排版方式
display: grid
或是display: inline-grid
。 - 畫草圖: 在放置物件之前,可以先把這個容器先劃分好空間來規劃一下那些物件應該放在哪個空間。這個步驟有點像是在正式繪圖之前會先畫個草稿才上色完稿、在蓋房子以前會先畫個設計圖才按設計圖蓋房子,所以個人是稱這個步驟為畫草圖。而劃分空間的方式大致有兩種:
- Explicit grid: 可以預先明確地(explicit)劃分出放置物件的空間,將物件放在這些空間;
- Implicit grid: 或者隱晦地(implicit)規範物件的排版方式,新增物件時就會按照這些規範排列。
- 定位物件 (Position): 可以說上面這些步驟是在設計一個網格系統,最後步驟就是將物件定位在設計好的網格系統。
下面範例以 display: grid;
為例去排版。
//html
<div class="wrapper">
<div>One</div>
<div>Two</div>
<div>Three</div>
<div>Four</div>
<div>Five</div>
</div>
// css
.wrapper{
display: grid;
}
Grid Tracks
設定好容器為 grid 排版,接著可用 Explicit Grid 和 Implicit Grid 屬性去實作排版。
Explicit grid:
grid-template-columns
grid-template-rows
Implicit grid:
grid-auto-columns
grid-auto-rows
Explicit Grid 是指明確地定義出 Grid Tracks,Grid Tracks 可以想成是預先將容器(wrapper)劃分出要置放物件的空間,譬如我們可以用 grid-template-columns
屬性預先決定一個頁面只能切割出三個物件寬的空間。
如果只用Explicit Grid,一些未被套用Explicit Grid的物件,Grid就會自動以預設(auto)方式處理,等同是 grid-auto-columns: auto;
或者 grid-auto-rows: auto;
。要注意若物件不包含任何內容(如文字),Grid不會在預設情況給予物件寬度/高度 ─ 意即沒有內容的物件不會顯示在畫面上,有內容的物件才會"撐出"物件的寬度/高度。
從這邊能發現有時預設排版不符所需,因此 Implicit Grid 屬性是用來告訴Grid,如果有物件超出或不在前述的定義範圍,又或者物件的文字內容等超出物件本身的大小,Grid 應該怎麼處理這些物件?
因為劃分空間的定義方式大同小異,以下會用 grid-template-columns
和 grid-auto-rows
列舉常見的定義方式
grid-template-columns
是對 column 方向排版,可以簡單想成是定義每個空間的 寬度。
這裡比較需要注意的是,Grid 有一個自己專門在容器內劃分空間大小的相對單位的 相對單位(Relative Unit) ─ fr
,另外 Grid 內排版可以混用絕對單位和相對單位。
grid-template-columns
grid-template-columns: 100px 100px 100px; // 每列3個寬度為100的div
grid-template-columns: 1fr 1fr 1fr; // 每列3個fr unit的div (fr= fraction)
grid-template-columns: 1fr 2fr 1fr;
grid-template-columns: repeat(3, 1fr); // 重複三次 1fr
grid-template-columns: repeat(3, 1fr 2fr); // 重複三次 1fr 2fr 組合
grid-template-columns: 50px repeat(3, 1fr) 100px; // mixed寫法 每列5個
如果只設定 grid-template-column
,而沒有加入 grid-template-row
屬性,代表 並沒有在 row 方向上明確劃分物件高度所佔的空間 給物件,因此 Grid 會偷偷以預設方式定義 row 方向的排版,也就是 Grid 會自行決定物件 高度,在這裡就等同是 grid-auto-rows: auto;
屬性。就像前面所說這些物件若沒有文字內容等,可能無法顯現(因為至少要有寬、高才會完整呈現一個物件)。
這裡可以使用 grid-auto-rows
屬性去事先 保證 這些物件至少應該有多少高度。譬如下面程式碼都是確保物件高度至少有50px,不一樣的是,若只寫 grid-auto-rows: 50px;
表示物件高度必須也只能佔50px;如果使用 minmax()
來給定高度,如 grid-auto-rows: minmax(50px, auto);
則表示物件高度 至少 有50px,並會隨著物件內容增長,詳情可參見 Codepen 範例。
grid-auto-rows
grid-auto-rows: 50px;
grid-auto-rows: minmax(50px, auto);
Grid Lines
當前面創造 Grid Tracks,Grid 會隨之定義 grid lines,並可在以 Explicit Grid 的排版系統作為物件定位基準,要注意 Implicit Grid 也會創造Lines,但無法用Lines定位。
Grid Line的排列方式是根據文件語言的書寫排版方式依序定義,例如以拉丁文件書寫方式而言就是由左往右、由上至下產生 Grid Lines。
下面Demo就是定位紅色物件必須在column line [1, 3]和row line [1, 3]之間。另外Grid line 也能命名定位,但這邊就不Demo了。
筆記的最後要留意的是,這裡只提到線 ─ Grid Lines 以及跟兩條線有關的空間 ─ Grid Tracks,Grid Lines 和 Grid Tracks 是用來作為物件定位的基準。
當劃分出空間以後,物件預設的定位是從 line 1 開始並且只擴展一個大小的空間,也因此才能在畫面上立即看到佔了一單位空間的物件。
另外如果劃分空間時希望定位的物件只佔一單位的空間,此時可只設定 grid-column-start
或 grid-row-start
(i.e., 省略設定 grid-column-start
或 grid-columrow-end
。
Grid系統最小單位稱 Grid Cells,而多個Grid Cells可組成Grid Area;如果要作出更細緻的配置或是預先命名一些空間再將物件放在這些已命名的空間可使用 grid-area
屬性,這部分就留待 下一篇繼續。
References