CSS 格線 - 表格版面配置已恢復。適時出現,抓住時機

TL;DR

如果您熟悉 Flexbox,Grid 應該會讓您覺得熟悉。Rachel Andrew 維護一個專門提供 CSS 格線資訊的優質網站,協助您開始使用。網格功能現已在 Google Chrome 中推出。

Flexbox?格狀檢視畫面?

過去幾年,CSS Flexbox 已廣泛使用,且瀏覽器支援情況也相當良好 (除非您是需要支援 IE9 以下版本的倒楣鬼)。Flexbox 讓許多複雜的版面配置工作變得更簡單,例如元素之間的等距離間距、由上而下的版面配置,或是 CSS 魔法師的聖杯:垂直置中。

無法在多個 Flexbox 容器中對齊元素。

不過,螢幕通常還有另一個需要注意的維度。很遺憾,除了自行處理元素大小以外,您無法只使用彈性容器來同時處理垂直和水平節奏。這時 CSS 格線就能派上用場。

CSS 格線一直在開發中,在大多數瀏覽器中已設為標記超過 5 年,我們也花了額外時間處理互通性問題,以免像 Flexbox 一樣推出時出現錯誤。因此,如果您在 Chrome 中使用 Grid 實作版面配置,在 Firefox 和 Safari 中也會獲得相同的結果。在撰寫本文時,Microsoft Edge 的 Grid 實作方式已過時 (與 IE11 中現有的相同),且更新處於「審查中」。

雖然 Flexbox 和 GridLayout 在概念和語法上有相似之處,但請勿將 Flexbox 和 GridLayout 視為競爭的版面配置技巧。格線會以兩個維度排列,而 Flexbox 則會以一個維度排列。兩者搭配使用時,可發揮相輔相成的作用。

定義格線

如要熟悉 Grid 的個別屬性,我誠摯推薦 Rachel Andrew 的 Grid By Example 或 CSS Tricks 的 Cheat Sheet。如果您熟悉 Flexbox,應該會對許多屬性及其含義感到熟悉。

我們來看看標準的 12 欄格格線版面配置。經典的 12 欄版面配置很受歡迎,因為 12 這個數字可被 2、3、4 和 6 整除,因此可用於許多設計。讓我們實作這個版面配置:

無法在多個 Flexbox 容器中對齊元素。

我們先從標記碼開始:

<!DOCTYPE html>
<body>
    <header></header>
    <nav></nav>
    <main></main>
    <footer></footer>
</body>

在樣式表中,我們會先擴展 body,讓其涵蓋整個檢視區,並將其轉換為格線容器

html, body {
    width: 100vw;
    min-height: 100vh;
    margin: 0;
    padding: 0;
}
body {
    display: grid;
}

我們現在使用 CSS 格線。正確無誤!

接下來,我們要實作網格的列和欄。我們可以在模擬圖中實作所有 12 個資料欄,但由於我們並未使用每個資料欄,因此這樣做會讓 CSS 不必要地雜亂。為求簡單起見,我們會以這種方式實作版面配置:

簡化版面配置範例

頁首和頁尾的寬度會變動,內容的兩個維度也會變動。導覽列也會在兩個維度中變化,但我們會將其寬度設為 200 像素的最低值。(原因為何?當然,這是為了展示 CSS 格線的功能)。

在 CSS 格線中,一組欄和列稱為「軌道」。我們先定義第一組軌道 (即資料列):

body {
    display: grid;
    grid-template-rows: 150px auto 100px;
}

grid-template-rows 會接收定義個別資料列的大小序列。在本例中,我們將第一列的高度設為 150 像素,最後一列則設為 100 像素。中間一列設為 auto,表示會調整至所需高度,以容納該列中的格狀項目 (格狀容器的子項)。由於身體會延伸至整個檢視區,因此包含內容的軌道 (上圖中的黃色) 至少會填滿所有可用空間,但在必要時會擴大 (並使文件捲動)。

我們希望在欄位方面採用更具彈性的做法:我們希望導覽和內容都能放大 (和縮小),但導覽欄位不得縮小至 200 像素以下,且內容必須大於導覽欄位。在 Flexbox 中,我們會使用 flex-grow 和 flex-shrink,但在 GridLayout 中,情況稍有不同:

body {
    display: grid;
    grid-template-rows: 150px auto 100px;
    grid-template-columns: minmax(200px, 3fr) 9fr;
}

我們定義了 2 個資料欄。第一欄是使用 minmax() 函式定義,該函式會採用 2 個值:該曲目的最小和最大大小。(就像 min-widthmax-width 一樣)。如先前所述,寬度不得低於 200 像素。寬度上限為 3frfr 是專屬於格線的單位,可讓您將可用空間分配給格線元素。fr 可能是「fraction unit」的縮寫,但也可能代表「free unit soon」。這裡的值表示兩個欄都會擴大填滿畫面,但內容欄的寬度一律是導覽欄的 3 倍 (前提是導覽欄的寬度必須大於 200 像素)。

雖然目前格狀項目的位置不正確,但列和欄的大小運作正常,並產生我們預期的行為:

放置項目

Grid 最強大的功能之一,就是可以不考慮 DOM 順序來放置項目。(不過,由於螢幕閱讀器會瀏覽 DOM,因此我們強烈建議您留意如何重新排序元素,以便確保適當的無障礙存取能力)。如果未完成手動放置作業,系統會依 DOM 順序將元素放置在格狀區塊中,並以由左至右、由上至下的方式排列。每個元素都會佔用一個儲存格。您可以使用 grid-auto-flow 變更填入格線的順序。

那麼,我們該如何放置元素?放置格線項目最簡單的方法,就是定義它們涵蓋哪些欄和列。Grid 提供兩種語法可用於這項操作:在第二個函式中,您會定義起點和跨度:

header {
    grid-column: 1 / 3;
}
nav {
    grid-row: 2 / span 2;
}
手動設定廣告插播時間點

我們希望標頭從第一欄開始,並在第 3 欄前面結束。導覽列應從第二列開始,總共跨越 2 列。

從技術層面來說,我們已完成版面配置的實作,但我想向您展示 Grid 提供的幾項便利功能,方便您更輕鬆地進行放置。第一個功能是,您可以為音軌邊框命名,並使用這些名稱進行放置:

body {
    display: grid;
    grid-template-rows: 150px [nav-start] auto 100px [nav-end];
    grid-template-columns: [header-start] minmax(200px, 3fr) 9fr [header-end];
}
header {
    grid-column: header-start / header-end;
}
nav {
    grid-row: nav-start / nav-end;
}

上述程式碼會產生與先前程式碼相同的版面配置。

更強大的功能是可為格狀圖中的整個區域命名:

body {
    display: grid;
    grid-template-rows: 150px auto 100px;
    grid-template-columns: minmax(200px, 3fr) 9fr;
    grid-template-areas: "header header"
                        "nav    content"
                        "nav    footer";
}
header {
    grid-area: header;
}
nav {
    grid-area: nav;
}

grid-template-areas 會採用以空格分隔的名稱字串,方便開發人員為每個儲存格命名。如果兩個相鄰的儲存格名稱相同,就會合併至同一區域。這樣一來,您就能為版面配置程式碼提供更多語意,並讓媒體查詢更直覺。同樣地,這個程式碼會產生與先前相同的版面配置。

還有其他問題嗎?

是的,是的,單一篇網誌文章無法涵蓋太多內容。Rachel Andrew 也是 GDE,也是 CSS 工作小組的邀請專家,從一開始就與他們合作,確保 Grid 能簡化網頁設計。她甚至寫了一本。她的網站「格狀檢視範例」是熟悉格狀檢視的寶貴資源。許多人認為格線是網頁設計的革命性一步,現在 Chrome 已預設啟用格線,您可以立即開始使用。