[译] Grid 布局完全指南
簡介
CSS 柵格布局 (亦稱 "Grid"),是一個基于柵格的二維布局系統,旨在徹底改變基于網格用戶界面的設計。CSS 一直以來并沒有把布局做的足夠好。剛開始,我們使用 tables,后來是 floats,positioning 和 inline-block,這些本質上是一些 hacks 而且許多重要功能尚未解決(例如垂直居中)。Flexbox 可以做到這些,但是它主要用來一些簡單的一維布局,并不適合復雜的二維布局(當然 Flexbox 與 Grid 可以一并使用)。Grid 是第一個為了解決布局問題的 CSS 模塊,只要我們做過網頁,就會遇到這些問題。
有兩件事情在激勵著我創作這篇指南,首先是 Rachel Andrew 那本非常不錯的書 Get Ready for CSS Grid Layout.,清晰透徹地介紹了 Grid,它是本篇文章的基礎。我強烈建議你去購買并且閱讀它。另一件事是 Chris Coyier 的文章 A Complete Guide to Flexbox,是關于 flexbox 的首選資源。它幫助了很多人,當你 Google "flexbox" 的時候,第一眼便能夠看見它。或許你已經注意到我的文章與它有很大相似之處,但我們有什么理由不借鑒它呢?
我會把 Grid 在最新版本規范上的概念呈現出來。因此,我將不會照顧過期的 IE 語法。當規范成熟時,我將盡可能去定期更新。
基礎與瀏覽器支持
開始 Grid 是簡單的,你僅僅需要在容器(container)元素上定義一個柵格使用 display: grid,并通過 grid-template-columns 與 grid-template-rows 設置行與列。通過設置 grid-column 和 grid-row 把子元素置于柵格中。與 flexbox 類似,柵格項目(items)的順序是無關緊要的,你可以通過 CSS 來控制順序。當使用媒體查詢時,改變它們的順序是極其簡單的。假設你設計好了網頁的布局,但你需要適應不同的屏幕寬度,這僅僅需要幾行代碼,Grid 是最為有效的模塊。
關于 Grid 一件非常重要的事情是你還不能夠在生產環境中使用它。它目前僅僅是一個 W3C工作草案,而且不能夠被任何瀏覽器默認支持。雖然IE10 與 IE11 能夠支持它,但使用了過期語法舊的實現。為了現在能夠體驗 Grid,最好的方法是使用 Chrome, Opera 或者 Firefox,并且開啟特定的標志。在 Chrome 中,導航到 chrome://flags 并且開啟 “experimental web platform features”。在 Opera 中同樣如此(opera://flags)。在 Firefox 中,開啟標志 layout.css.grid.enabled(about:config)。
這有一張瀏覽器支持表格,我將保持更新。
Chrome 29+ (Behind flag)
Safari Not supported
Firefox 40+ (Behind flag)
Opera 28+ (Behind flag)
IE 10+ (Old syntax)
Android Not supported
iOS Not supported
譯者注:現在有些最新瀏覽器的最新版本已經能夠支持,可以查看 caniuse 網站。
你在生產環境中使用它僅僅是一個時間問題。但是,學習正在當下!
重要術語
在深入了解 Grid 概念之前,了解它的術語是極為重要的。因為在此涉及到的術語概念相似,不易混淆。不過不用擔心,他們并沒有很多。
Grid Container (柵格容器)
設置 display: grid 的元素,它是所有柵格項目的直接父級元素。在這個例子中,container 是柵格的容器。
<div class="container"><div class="item item-1"></div><div class="item item-2"></div><div class="item item-3"></div> </div>Grid Item (柵格項目)
柵格容器的直接子代。在這里 item 是柵格項目,而 sub-item 不是柵格項目。
<div class="container"><div class="item"></div> <div class="item"><p class="sub-item"></p></div><div class="item"></div> </div>Grid Line (柵格線)
組成柵格結構的分割線。它們位于行與列的兩側,有的是垂直的(列柵格線),有的是水平的(行柵格線)。以下黃色線是一個列柵格線。
Grid Track (柵格軌跡)
相鄰柵格線的區域。你可以認為他們是柵格的一行或者一列。以下是第二與第三柵格線間的柵格軌跡。
Grid Cell (柵格格子)
相鄰行柵格線與相鄰列柵格線間的區域。它是柵格的獨立“單元”。以下柵格格子位于1,2行柵格線與2,3列柵格線間。
Grid Area (柵格區域)
被四個柵格線圍繞的區域。一個柵格區域由任意數量的柵格格子組成。以下柵格區域位于1,3行柵格線與1,3列柵格線間。
柵格屬性內容表
屬于柵格容器的屬性:
display
grid-template-columns
grid-template-rows
grid-template-areas
grid-column-gap
grid-row-gap
grid-gap
justify-items
align-items
justify-content
align-content
grid-auto-columns
grid-auto-rows
grid-auto-flow
grid
屬于柵格項目的屬性:
grid-column-start
grid-column-end
grid-row-start
grid-row-end
grid-column
grid-row
grid-area
justify-self
align-self
柵格容器屬性(Grid Container)
display
定義該元素為柵格項目,并且為它的內容建立一個新的柵格格式上下文(grid formatting context)。
譯者注:還記得 BFC 與 IFC 嗎?
屬性值:
grid 生成塊狀柵格
inline-grid 生成行間柵格
subgrid 如果你的柵格容器本身是一個柵格項目的話(例如:嵌套柵格),你可以根據它的父元素而不是它自己,指定行列大小。
注意:column,float,clear 與 vertical-align 在柵格容器上無效。
grid-template-columns
grid-template-rows
通過空格分隔的值定義柵格的行與列。值代表軌跡大小(track size),它們中間的間隙代表柵格線。
屬性值:
<track-size> 可以是長度,百分比,或者柵格中的空白空間(使用 fr)
<line-name> 任意名字,任君選擇
示例:
當你在軌跡值之間預留空格時,柵格線會被自動分配為數值名字。
.container{grid-template-columns: 40px 50px auto 50px 40px;grid-template-rows: 25% 100px auto; }
你也可以為柵格線設置名字,注意柵格線名字的括號語法:
.container{grid-template-columns: [first] 40px [line2] 50px [line3] auto [col4-start] 50px [five] 40px [end];grid-template-rows: [row1-start] 25% [row1-end] 100px [third-line] auto [last-line]; }
注意一條線可以有多個名字。例如,這里第二條線有兩個名字:row1-end 和 row2-start。
.container{grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end]; }如果你定義的內容包含重復部分,你可以使用 repeat() 標記去組織它。
.container{grid-template-columns: repeat(3, 20px [col-start]) 5%; }與以下代碼是等價的
.container{grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%; }fr 允許你設置軌跡大小為柵格容器的一部分。例如,以下示例將設置每個項目為柵格容器的三分之一。
.container{grid-template-columns: 1fr 1fr 1fr; }空白空間將在固定項目 之后 被計算。在這個例子中,給 fr 分配的全部空余時間不包括 50px。
.container{grid-template-columns: 1fr 50px 1fr 1fr; }grid-template-areas
通過指定柵格區域的名字來定義柵格模板,這樣柵格項目會通過 grid-area 屬性來指定區域。重復柵格區域的名字將會合并柵格格子,一個句點表示一個空的柵格格子。語法本身提供了一個可視化的柵格結構。
屬性值:
<grid-area-name> 在項目中使用 grid-area 屬性指定的柵格區域
. 句點表示空白柵格格子
none 不定義柵格區域
示例:
.item-a{grid-area: header; } .item-b{grid-area: main; } .item-c{grid-area: sidebar; } .item-d{grid-area: footer; }.container{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" }這將建造一個三行四列的柵格。第一行全部由 header 區域組成,第二行由兩個 main 區域,一個空白格子與一個 sidebar 區域組成。最后一行全部由 footer 組成。
你聲明的每行都需要有相同數量的柵格格子。
你可以使用任意數量無空格分割的相鄰句點去表示單個空白柵格格子。
譯者注:grid-template-areas: "first . last" 與 grid-template-areas: "first ...... last" 等價。
注意,這種語法僅僅能命名區域,而無法命名柵格線。實際上,當你使用這種語法的時候,柵格區域兩端的柵格線已被自動命名。如果你的柵格區域叫 foo,柵格區域開始的行與列將被命名為 foo-start,而結束的行與列將被命名為 foo-end。這意味著一些柵格線會有很多名字,比如上述例子的最左邊的柵格線將會有三個名字:header-start, main-start 和 footer-start。
grid-template
grid-template-columns,grid-template-rows 和 grid-template-areas 的簡寫。
屬性值:
none 設置這三個屬性為初始屬性
subgrid 設置 grid-template-rows 和 grid-template-columns 為 subgrid,grid-template-areas 為初始值。
<grid-template-columns> / <grid-template-rows> 設置 grid-template-columns 與 grid-template-rows 為各自指定的值。而 grid-template-areas 為 none。
另外,也有一個比較復雜但是方便的語法指定三個屬性,示例如下
.container{grid-template: auto 50px auto /[row1-start] 25px "header header header" [row1-end][row2-start] "footer footer footer" 25px [row2-end]; }與以下代碼是等價的:
.container{grid-template-columns: auto 50px auto;grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];grid-template-areas: "header header header" "footer footer footer"; }因為 grid-template 無法 隱式 重置屬性(grid-auto-columns,grid-auto-rows 與 grid-auto-flow)。或許你想做更多的事,那么推薦你使用 grid 屬性去替代 grid-template。
grid-column-gap
grid-row-gap
指定柵格線的大小,你可以理解它為設置行/列間隙。
屬性值:
<line-size> 長度值
示例:
.container{grid-template-columns: 100px 50px 100px;grid-template-rows: 80px auto 80px; grid-column-gap: 10px;grid-row-gap: 15px; }
柵格間隙僅僅在行/列 之間,不包括最外部的邊。
grid-gap
grid-column-gap 與 grid-row-gap 的簡寫。
屬性值:
<grid-row-gap> <grid-column-gap> 長度值
示例:
.container{grid-template-columns: 100px 50px 100px;grid-template-rows: 80px auto 80px; grid-gap: 10px 15px; }如果沒有設置 grid-row-gap,它將于 grid-column-gap 保持一致。
justify-items
使柵格項目中的內容與 列 軸對齊(相應地,align-items 與 行 軸對齊)。這個屬性值應用在容器中的所有項目上。
屬性值:
start 使內容與柵格區域左側對齊
end 使內容與柵格區域右側對齊
center 使內容在柵格區域中居中
stretch 使內容充滿整個柵格區域的寬(默認屬性)
示例
.container{justify-items: start; }.container{justify-items: end; }
.container{justify-items: center; }
.container{justify-items: stretch; }
這個行為也可以通過 justify-self 屬性設置在獨立的柵格項目上。
align-items
使柵格項目中的內容與 行 軸對齊(相應地,justify-items 與 列 軸對齊)。這個屬性值應用在容器中的所有項目上。
屬性值:
start 使內容與柵格區域頂部對齊
end 使內容與柵格區域底部對齊
center 使內容在柵格區域中居中
stretch 使內容充滿整個柵格區域的高(默認屬性)
示例:
.container{align-items: start; }.container{align-items: end; }
.container{align-items: center; }
.container{align-items: stretch; }
這個行為也可以通過 align-self 屬性設置在獨立的柵格項目上。
justify-content
有時候,柵格的總大小小于柵格容器的大小,比如你使用 px 給所有的柵格項目設置了固定大小。本例中,你可以設置柵格容器中柵格的對齊。這個屬性會使柵格與 列 軸對齊(相應地,align-content 會使柵格與 行 軸對齊)。
屬性值:
start 與柵格容器的左側對齊
end 與柵格容器的右側對齊
center 在柵格容器中居中
stretch 調整柵格項目的大小,使柵格充滿整個柵格容器。
space-around 每兩個項目之間留有相同的空白,在最左端與最右端為一半大小的空白。
space-between 每兩個項目之間留有相同的空白,在最左端與最右端不留空白。
space-evenly 每兩個項目之間留有相同的空白,包括兩端。
示例:
.container{justify-content: start; }.container{justify-content: end; }
.container{justify-content: center; }
.container{justify-content: stretch; }
.container{justify-content: space-around; }
.container{justify-content: space-between; }
.container{justify-content: space-evenly; }
align-content
有時候,柵格的總大小小于柵格容器的大小,比如你使用 px 給所有的柵格項目設置了固定大小。本例中,你可以設置柵格容器中柵格的對齊。這個屬性會使柵格與 行 軸對齊(相應地,align-content 會使柵格與 列 軸對齊)。
屬性值:
start 與柵格容器的頂部對齊
end 與柵格容器的底部對齊
center 在柵格容器中居中
stretch 調整柵格項目的大小,使柵格充滿整個柵格容器。
space-around 每兩個項目之間留有相同的空白,在最左端與最右端為一半大小的空白。
space-between 每兩個項目之間留有相同的空白,在最左端與最右端不留空白。
space-evenly 每兩個項目之間留有相同的空白,包括兩端。
示例:
.container{align-content: start; }.container{align-content: end; }
.container{align-content: center; }
.container{align-content: stretch; }
.container{align-content: space-around; }
.container{align-content: space-between; }
.container{align-content: space-evenly; }
grid-auto-columns
grid-auto-rows
指定自動生成的柵格軌跡的大小(亦稱隱式柵格軌跡)。當你顯式定位行與列的時候(通過 grid-template-rows / grid-template-columns),隱式柵格軌跡會在定義的柵格外被創建。
屬性值:
<track-size> 可以是長度,百分比或者 fr
舉例了解隱式柵格軌跡是如何被創建的,考慮以下示例:
.container{grid-template-columns: 60px 60px;grid-template-rows: 90px 90px }
本示例建造了 2 * 2 的柵格。
你使用 [grid-column](#prop-grid-column) 與 grid-row 去定位你的項目如下:
.item-a{grid-column: 1 / 2;grid-row: 2 / 3; } .item-b{grid-column: 5 / 6;grid-row: 2 / 3; }
我們告知 .item-b 在 5-6 列間,但我們從未定義第五列或者第六列。因為我們引用的柵格線不存在,寬度為0的隱式柵格軌跡將會創建去填充空白。我們可以使用 grid-auto-columns 和 grid-auto-rows 去指定這些軌跡的寬。
譯者注:經譯者測試,并非以寬度為0的 implicit track 去填充。w3c auto-tracks 上表明 grid-auto-columns 的默認值為 auto,則超過的列將會平分空白空間。
.container{grid-auto-columns: 60px; }
grid-auto-flow
如果你的柵格項目沒有顯式地在柵格中設置位置,自動放置算法便會生效。這個屬性控制自動放置算法的的運作。
屬性值:
row 自動放置算法將按行依次排列,按需添加新行。
column 自動放置算法將按列依次排列,按需添加新列。
dense 如果較小的項目出現靠后時,自動防止算法將盡可能早地填充柵格的空白格子
注意 dense 可能使你的項目次序顛倒。
示例:
考慮以下 html:
<section class="container"><div class="item-a">item-a</div><div class="item-b">item-b</div><div class="item-c">item-c</div><div class="item-d">item-d</div><div class="item-e">item-e</div> </section>你定義了一個兩行五列的柵格,并設置它的 grid-auto-flow 屬性為 row (默認屬性便是 row)。
.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; }因為我們設置了 grid-auto-flow 屬性為 row,呈現在我們眼前的柵格便是如下這個樣子。注意,這三個項目(item-b,item-c 與 item-d)并沒有特意指定位置。
如果設置 grid-auto-flow 的屬性為 column,item-b,item-c 與 item-d** 將按列以此排序。
.container{display: grid;grid-template-columns: 60px 60px 60px 60px 60px;grid-template-rows: 30px 30px;grid-auto-flow: column; }
grid
以下屬性的縮寫:grid-template-rows, grid-template-columns, grid-template-areas,grid-auto-rows,grid-auto-columns,與 [grid-auto-flow](#prop-grid-auto-flow)。它也可以設置 grid-column-gap 和 grid-row-gap為默認值,即使并沒有在 grid 中明確設置。
屬性值:
none 設置所有子屬性的值為初始值。
<grid-template-rows> / <grid-template-columns> 僅僅設置這兩個屬性值,其它子屬性值為初始值。
<grid-auto-flow> [<grid-auto-rows> [ / <grid-auto-columns>] ] 如果 grid-auto-columns 屬性值確實,則采用 grid-auto-rows的值。如果屬性值均缺失,則采用默認值。
以下兩種寫法是等價的:
.container{grid: 200px auto / 1fr auto 1fr; } .container{grid-template-rows: 200px auto;grid-template-columns: 1fr auto 1fr;grid-template-areas: none; }以下兩種寫法也是等價的:
.container{grid: column 1fr / auto; } .container{grid-auto-flow: column;grid-auto-rows: 1fr;grid-auto-columns: auto; }另外你可以設置更為復雜但相當方便的語法一次性設置所有屬性。你可以指定grid-template-areas, grid-auto-rows 與 grid-auto-columns,其他子屬性將被設為默認值。你需要指定柵格線與軌跡大小,這很容易用一個例子表示:
.container{grid: [row1-start] "header header header" 1fr [row1-end][row2-start] "footer footer footer" 25px [row2-end]/ auto 50px auto; }與以下寫法是等價的:
.container{grid-template-areas: "header header header""footer footer footer";grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];grid-template-columns: auto 50px auto; }柵格項目屬性 (Grid Items)
grid-column-start
grid-column-end
grid-row-start
grid-row-end
通過指定柵格線來確定柵格項目的位置。grid-column-start / grid-row-start 代表項目開始的線,grid-column-end/grid-row-end 代表項目結束的線。
屬性值:
<Line> 可以是一個表示柵格線名字或數字。
span <number> 項目將橫跨指定數量柵格軌跡
span <name> 項目將橫跨至指定名字的柵格線
auto 自動放置,自動跨越軌跡或者默認跨越軌跡
示例:
.item-a{grid-column-start: 2;grid-column-end: five;grid-row-start: row1-startgrid-row-end: 3 }.item-b{grid-column-start: 1;grid-column-end: span col4-start;grid-row-start: 2grid-row-end: span 2 }
如果沒有指定 grid-column-end/grid-row-end,項目默認橫跨一個軌跡。
項目可能會互相重疊,你可以使用 z-index 控制它們的層疊順序(stacking order)。
grid-column
grid-row
各自表示grid-column-start + grid-column-end 與 grid-row-start + grid-row-end的縮寫。
屬性值:
<start-line> / <end-line> 接收 grid-column-start 同樣的屬性值,包括 span
Example:
.item-c{grid-column: 3 / span 2;grid-row: third-line / 4; }
如果沒有指定 end line,項目將默認跨越一個軌跡。
grid-area
當創建柵格容器使用 grid-template-areas 屬性時,可以通過制定區域名字確定柵格項目的位置。同樣,它也可以作為以下屬性的縮寫:grid-row-start + grid-column-start + grid-row-end + grid-column-end。
屬性值:
<name>
<row-start> / <column-start> / <row-end> / <column-end>
示例:
你可以給項目設置名字:
.item-d{grid-area: header }也可以作為grid-row-start + grid-column-start + grid-row-end + grid-column-end 的縮寫:
.item-d{grid-area: 1 / col4-start / last-line / 6 }
justify-self
使柵格項目中的內容與 列 軸對齊(相應地,align-self 與 行 軸對齊)。本屬性值適用于單個項目的內容。
屬性值:
start 使內容與柵格區域左側對齊
end 使內容與柵格區域右側對齊
center 使內容在柵格區域中居中
stretch 使內容充滿整個柵格區域的寬(默認屬性)
示例:
.item-a{justify-self: start; }.item-a{justify-self: end; }
.item-a{justify-self: center; }
.item-a{justify-self: stretch; }
為了對柵格項目中的所有項目設置對齊,可以是指柵格容器的 justify-items 屬性。
align-self
使柵格項目中的內容與 行 軸對齊(相應地,justify-self 與列軸對齊)。本屬性值適用于單個項目的內容。
屬性值:
start 使內容與柵格區域頂部對齊
end 使內容與柵格區域底部對齊
center 使內容在柵格區域中居中
stretch 使內容充滿整個柵格區域的高(默認屬性)
示例:
.item-a{align-self: start; }.item-a{align-self: end; }
.item-a{align-self: center; }
.item-a{align-self: stretch; }
為了對柵格項目中的所有項目設置對齊,可以設置柵格容器的 align-items 屬性。
總結
以上是生活随笔為你收集整理的[译] Grid 布局完全指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 并发数据结构- 1.1.1 性能
- 下一篇: Android测试提升效率批处理脚本