在講布局前,先說兩句題外話,寫博時,突然想到了郭德綱說過的一個段子“說兩個人罵架,不是你有理,你嗓門大,你唾沫星子崩我一臉,你就能罵贏,要看誰命長,過兩年你死了,我站你墳頭咋說咋是對的,你在那小匣里還能站起來說啥不”。
為什么要說這個老梗呢,其實前端寫頁面布局,差不多就是這個道理,咱們(小子沒學幾天,這里說‘咱們’全當應景)之前用的都是啥,我來一張圖:
差不多就是這個了吧,對付了幾年,終於看見了點太陽,就都用flexbox了,雖然也沒全面鋪開吧,不過你自己說,是不是用着比之前爽多了,而我接下來要說的,就是就是布局界里的一道絕對的曙光,Grid。
你得好好學習啊,在這行道上多走幾年,把瀏覽器規范熬統一了,哪怕熬黃了IE呢,是不是以后的路就好走了。
下面這中二維布局方式,如果你們現在用不上,也花擼一把的時間看一下,等人家過兩年允許扛槍了,你還叉着刺刀喊沖鋒呢。
其實你們不學也好,省着跟我搶飯碗,哇哈哈哈...
初步了解和瀏覽器支持
使用Grid布局非常簡單,你只需要給容器(container)定義:display:grid,並設置列(grid-template-columns)和 行(grid-template-rows)的大小,然后用grid-column和grid-row定義容器子元素(grid-item項目)的位置。與flexbox布局類似,一開始項目的排列順序並不重要,可以放置在容器的任何位置,這也使得你非常容易通過媒體查詢重新排列你的項目。想象一下,當你定義整個頁面的布局時,你只需要幾行CSS就可以完成頁面重排以便適應各種屏幕寬度,這得有多么神奇!
好東西總是來的晚,不要焦躁,不要沮喪。活好每一天,自然就等到了。
目前瀏覽器還不支持Grid布局,IE10和IE11支持老的語法。如果你想體驗Grid布局的強大,推薦使用開通過“體驗新功能”的Chrome, Opera 或 Firefox, Chrome:打開瀏覽器,輸入chrome://flags,找到"experimental web platform features",啟用並重啟瀏覽器;Opera:輸入opera://flags,與Chrome一樣;Firefox:輸入layout.css.grid.enabled。
瀏覽器支持情況:
| Chrome | Safari | Firefox | Opera | IE | Android/iOS |
|---|---|---|---|---|---|
| 29+ (Behind flag) | Not supported | 40+ (Behind flag) | 28+ (Behind flag) | 10+ (Old syntax) | Not supported |
重要術語
在深入了解Grid布局概念之前,我們先了解一些術語。因為這些術語在概念上很相似,如果你不記住Grid定義的含義,會很容易將它們混淆,但是不用擔心,這里術語很少。
1.網格容器(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>
2.網格項(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>
3.網格線(Grid Line)
組成網格線的分界線。它們可以是列網格線(column grid lines),也可以是行網格線(row grid lines)並且居於行或列的任意一側,下面黃色線就是列網格線。
4.網格軌道(Grid Track)
兩個相鄰的網格線之間為網格軌道。你可以認為它們是網格的列或行,下面在第二個和第三個網格線之間的黃色部分為網格軌道。
5.網格單元(Grid Cell)
兩個相鄰的列網格線和兩個相鄰的行網格線組成的是網格單元,它是最小的網格單元。下面行網格線1(row grid lines 1)、行網格線2(row grid lines 2)和列網格線1(column grid lines 1)、列網格線2(column grid lines2)組成的黃色區域為網格單元。
6.網格區(Grid Area)
網格區是由任意數量網格單元組成,下面行網格線1(row grid lines 1)、行網格線3(row grid lines 3)和列網格線1(column grid lines 1)、列網格線3(column grid lines3)組成的黃色區域為網格區。
設置在網格容器上的屬性
- 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
1. display: grid | inline-grid | subgrid;
屬性值:
grid: 生成塊級網格
inline-grid: 生成行內網格
subgrid: 如果網格容器本身是網格項(嵌套網格容器),此屬性用來繼承其父網格容器的列、行大小。
注:當元素設置了網格布局,column、float、clear、vertical-align屬性無效。
2. grid-template-columns: <track-size> ... | <line-name> <track-size> ... ;
grid-template-rows: <track-size> ... | <line-name> <track-size> ... ;
設置行和列的大小,在行軌道或列軌道兩邊是網格線。
屬性值:
track-size: 軌道大小,可以使用css長度,百分比或用分數(用fr單位)。
line-name: 網格線名字,你可以選擇任何名字。
例子:
當你設置行或列大小為auto時,網格會自動分配空間和網格線名稱。
.container{ display:grid; grid-template-columns: 40px 50px auto 50px 40px; grid-template-rows: 25% 100px auto; }
你也可以給網格線定義名字,注意名字需要寫在[]里面。
.container{ display:grid; 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{ display:grid; grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end]; }
如果你定義包含重復部分,可以使用repeat()簡化。
.container{ display:grid; grid-template-columns: repeat(3, 20px [col-start]) 5%; }
上面等同於下面:
.container{ display:grid; grid-template-columns: 20px [col-start] 20px [col-start] 20px [col-start] 5%; }
用fr單位可以將容器分為幾等份,例如下面分成三等份。
.container{ display:grid; grid-template-columns: 1fr 1fr 1fr; }
如果fr單位和實際值一起使用,設置fr的行或列將分(除了實際值)剩余部分。
.container{ display:grid; grid-template-columns: 1fr 50px 1fr 1fr; }
3.grid-template-areas
通過獲取網格項中的grid-area屬性值(名稱),來定義網格模版。重復網格區(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{ 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" }
上面代碼示例會創建四列三行網格,第一行將是header,第二行前兩個網格單元是main部分、第三個為空網格單元、第四個為sliderbar,第三行是footer。
4. grid-column-gap:<line-size>; 和 grid-row-gap: <line-size> ;
網格單元間距。
屬性值:
line-size: 網格線間距,設置單位值。
例子:
.container{ display:grid; grid-template-columns: 100px 50px 100px; grid-template-rows: 80px auto 80px; grid-column-gap: 10px; grid-row-gap: 15px; }
注:間隔僅僅作用在網格單元之間,不作用在容器邊緣。
5. grid-gap:<grid-column-gap> <grid-row-gap>;
是grid-column-gap 和 grid-row-gap簡寫。
例子:
.container{ display:grid; grid-template-columns: 100px 50px 100px; grid-template-rows: 80px auto 80px; grid-gap: 10px 15px; }
注:如果只設置一個值,那么grid-column-gap 和 grid-row-gap都為那個值。
6. justify-items: start | end | center | stretch(默認) ;
垂直於列網格線對齊,適用於網格容器里的所有網格項。
屬性值:
start: 左對齊。
end: 右對齊。
center: 居中對齊。
stretch: 填滿(默認)。
例子:
.container{ display:grid; justify-items: start; }
.container{ display:grid; justify-items: end; }
.container{ display:grid; justify-items: center; }
.container{ display:grid; justify-items: stretch; }
7. align-items: start | end | center | stretch ;
垂直於行網格線對齊,適用於網格容器里的所有網格項。
屬性值:
start: 頂部對齊。
end: 底部對齊。
center: 居中對齊。
stretch:填滿(默認)。
例子:
.container{ display:grid; align-items: start; }
.container{ display:grid; align-items: end; }
.container{ display:grid; align-items: center; }
.container{ display:grid; align-items: stretch; }
8. justify-content: start | end | center | stretch | space-around | space-between | space-evenly ;
如果用像px非彈性單位定義的話,總網格區域大小有可能小於網格容器,這時候你可以設置網格的對齊方式(垂直於列網格線對齊)。
屬性值:
start: 左對齊。
end: 右對齊。
center: 居中對齊。
stretch: 填滿網格容器。
space-around: 網格項兩邊間距相等,網格項之間間隔是單側的2倍。
space-between: 兩邊對齊,網格項之間間隔相等。
space-evenly: 網格項間隔相等。
例子:
.container{ display:grid; justify-content: start; }
.container{ display:grid; justify-content: end; }
.container{ display:grid; justify-content: center; }
.container{ display:grid; justify-content: stretch; }
.container{ display:grid; justify-content: space-around; }
.container{ display:grid; justify-content: space-between; }
.container{ display:grid; justify-content: space-evenly; }
9. align-content: start | end | center | stretch | space-around | space-between | space-evenly ;
如果用像px非彈性單位定義的話,總網格區域大小有可能小於網格容器,這時候你可以設置網格的對齊方式(垂直於行網格線對齊)。
屬性值:
start: 頂部對齊。
end: 底部對齊。
center: 居中對齊。
stretch: 填滿網格容器。
space-around: 網格項兩邊間距相等,網格項之間間隔是單側的2倍。
space-between: 兩邊對齊,網格項之間間隔相等。
space-evenly: 網格項間隔相等。
例子:
.container{ display:grid; align-content: start; }
.container{ display:grid; align-content: end; }
.container{ display:grid; align-content: center; }
.container{ display:grid; align-content: stretch; }
.container{ display:grid; align-content: space-around; }
.container{ display:grid; align-content: space-between; }
.container{ display:grid; align-content: space-evenly; }
10. grid-auto-columns: <track-size> ... ; 和 grid-auto-rows: <track-size> ... ;
自動生成隱式網格軌道(列和行),當你定位網格項超出網格容器范圍時,將自動創建隱式網格軌道。
屬性值:
track-size: 網格軌道大小,可以是固定值,百分比或者是分數(fr單位)。
為了說明隱式網格軌道是怎么創建的,我們先看下面列子:
.container{ display:grid; grid-template-columns: 60px 60px; grid-template-rows: 90px 90px }
這是2✖️2的網格,但是我們來用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定位在第五根列網格線(column line 5 )和第六根列網格線(column line 6 )之間。但是我們網格容器根本不存在這兩條網格線,所以就用兩個0寬度來填充。在這里我們可以用網格自動行(grid-auto-rows)和網格自動列(grid-auto-columns)來定義這些隱式軌道寬度。
.container{ display:grid; grid-auto-columns: 60px; }
11. grid-auto-flow : row(默認) | column | dense ;
在沒有設置網格項的位置時,這個屬性控制網格項怎樣排列。
屬性值:
row: 按照行依次從左到右排列。
column: 按照列依次從上倒下排列。
dense: 按先后順序排列。
來看看下面結構:
<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>
下面定義5列2行網格,同時定義grid-auto-flow: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;結果如下:
12. grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [ / <grid-auto-columns>] ];
是一種簡寫形式,設置網格容器所有屬性。
屬性值:
none: 設置為所有屬性的默認值。
<grid-template-rows> / <grid-template-columns>: 設置行和列的值,其他屬性為默認值。
<grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns>] ] : 設置網格自動流、網格自動行、網格自動列的值,其他未設置則為默認值。
例子1:
.container{ grid: 200px auto / 1fr auto 1fr; }
等同於
.container{ grid-template-rows: 200px auto; grid-template-columns: 1fr auto 1fr; grid-template-areas: none; }
例子2:
.container{ grid: column 1fr / auto; }
等同於
.container{ grid-auto-flow: column; grid-auto-rows: 1fr; grid-auto-columns: auto; }
設置在網格項上的屬性
- grid-column-start
- grid-column-end
- grid-row-start
- grid-row-end
- grid-column
- grid-row
- grid-area
- justify-self
- align-self
1. 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 ;
通過網格線來定義網格項的位置。grid-column-start、grid-row-start定義網格項的開始位置,grid-column-end、grid-row-end定義網格項的結束位置。
屬性值:
line: 指定帶編號或者名字的網格線。
span <number>: 跨越軌道的數量。
span <name>: 跨越軌道直到對應名字的網格線。
auto: 自動展示位置,默認跨度為1。
例子:
.item-a{ grid-column-start: 2; grid-column-end: five; grid-row-start: row1-start grid-row-end: 3 }
.item-b{ grid-column-start: 1; grid-column-end: span col4-start; grid-row-start: 2 grid-row-end: span 2 }
注:如果未聲明grid-column-end或grid-row-end,默認將跨越一個軌道。項目也可以重疊,設置z-index來確定堆疊順序。
2. grid-column: <start-line> / <end-line> | <start-line> / span <value> ;
grid-row: <start-line> / <end-line> | <start-line> / span <value> ;
是 grid-column-start、grid-column-end 和 grid-row-start、grid-row-end 的簡寫。
例子:
.item-c{ grid-column: 3 / span 2; grid-row: third-line / 4; }
3. grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end> ;
定義網格項名字,以便創建模塊(容器屬性grid-template-areas來定義模塊)。
屬性值:
name: 項目名子。
<row-start> / <column-start> / <row-end> / <column-end>: 可以是數字或網格線名字。
例子:
定義網格項名字:
.item-d{ grid-area: header }
通過網格線定位網格項:
.item-d{ grid-area: 1 / col4-start / last-line / 6 ; }
4. justify-self: justify-self: start | end | center | stretch;
定義單個網格項垂直於列網格線的對齊方式。
屬性值:
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,達到全部網格項對齊。
5. align-self: start | end | center | stretch;
定義單個網格項垂直於行網格線的對齊方式。
屬性值:
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,達到全部網格項對齊。
結束
這篇文章翻譯自A Complete Guide to Grid,作者是CHRIS HOUSE。里面也加入了一些我個人的理解。文章有點長,屬性容易混淆,邊看邊練習會比較容易理解和記住。
本文來自博客: http://peale.cn/
