CSS網(wǎng)格布局(又稱“網(wǎng)格”),是一種二維網(wǎng)格布局系統(tǒng)。CSS在處理網(wǎng)頁布局方面一直做的不是很好。一開始我們用的是table(表格)布局,然后用float(浮動),position(定位)和inline-block(行內(nèi)塊)布局,但是這些方法本質(zhì)上是hack,遺漏了很多功能,例如垂直居中。后來出了flexbox(盒子布局),解決了很多布局問題,但是它僅僅是一維布局,而不是復(fù)雜的二維布局,實際上它們(flexbox與grid)能很好的配合使用。Grid布局是第一個專門為解決布局問題而創(chuàng)建的CSS模塊,2012年11月06日成立草案。
初步了解和瀏覽器支持
使用Grid布局非常簡單,你只需要給容器(container)定義:display:grid,并設(shè)置列(grid-template-columns)和 行(grid-template-rows)的大小,然后用grid-column和grid-row定義容器子元素(grid-item項目)的位置。與flexbox布局類似,一開始項目的排列順序并不重要,可以放置在容器的任何位置,這也使得你非常容易通過媒體查詢重新排列你的項目。想象一下,當(dāng)你定義整個頁面的布局時,你只需要幾行CSS就可以完成頁面重排以便適應(yīng)各種屏幕寬度,這得有多么神奇!
好東西總是來的晚,不要焦躁,不要沮喪?;詈妹恳惶?,自然就等到了。
目前瀏覽器還不支持Grid布局,IE10和IE11支持老的語法。如果你想體驗Grid布局的強(qiáng)大,推薦使用開通過“體驗新功能”的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
重要術(shù)語
在深入了解Grid布局概念之前,我們先了解一些術(shù)語。因為這些術(shù)語在概念上很相似,如果你不記住Grid定義的含義,會很容易將它們混淆,但是不用擔(dān)心,這里術(shù)語很少。
1.網(wǎng)格容器(Grid Container)
元素應(yīng)用display:grid,它是其所有網(wǎng)格項的父元素。下面例子container就是網(wǎng)格容器。
<div class="container"> <div class="item item-1"></div> <div class="item item-2"></div> <div class="item item-3"></div></div>
2.網(wǎng)格項(Grid Item)
網(wǎng)格容器的子元素,下面的item元素是網(wǎng)格項,但sub-item不是。
<div class="container"> <div class="item"></div> <div class="item"> <p class="sub-item"></p> </div> <div class="item"></div></div>
3.網(wǎng)格線(Grid Line)
組成網(wǎng)格線的分界線。它們可以是列網(wǎng)格線(column grid lines),也可以是行網(wǎng)格線(row grid lines)并且居于行或列的任意一側(cè),下面黃色線就是列網(wǎng)格線。
4.網(wǎng)格軌道(Grid Track)
兩個相鄰的網(wǎng)格線之間為網(wǎng)格軌道。你可以認(rèn)為它們是網(wǎng)格的列或行,下面在第二個和第三個網(wǎng)格線之間的黃色部分為網(wǎng)格軌道。
5.網(wǎng)格單元(Grid Cell)
兩個相鄰的列網(wǎng)格線和兩個相鄰的行網(wǎng)格線組成的是網(wǎng)格單元,它是最小的網(wǎng)格單元。下面行網(wǎng)格線1(row grid lines 1)、行網(wǎng)格線2(row grid lines 2)和列網(wǎng)格線2(column grid lines 2)、列網(wǎng)格線3(column grid lines 3)組成的黃色區(qū)域為網(wǎng)格單元。
6.網(wǎng)格區(qū)(Grid Area)
網(wǎng)格區(qū)是由任意數(shù)量網(wǎng)格單元組成,下面行網(wǎng)格線1(row grid lines 1)、行網(wǎng)格線3(row grid lines 3)和列網(wǎng)格線1(column grid lines 1)、列網(wǎng)格線3(column grid lines3)組成的黃色區(qū)域為網(wǎng)格區(qū)。
設(shè)置在網(wǎng)格容器上的屬性
1. display: grid | inline-grid | subgrid;
屬性值:
grid: 生成塊級網(wǎng)格
inline-grid: 生成行內(nèi)網(wǎng)格
subgrid: 如果網(wǎng)格容器本身是網(wǎng)格項(嵌套網(wǎng)格容器),此屬性用來繼承其父網(wǎng)格容器的列、行大小。
注:當(dāng)元素設(shè)置了網(wǎng)格布局,column、float、clear、vertical-align屬性無效。
2. grid-template-columns: <track-size> ... | <line-name> <track-size> ... ;
grid-template-rows: <track-size> ... | <line-name> <track-size> ... ;
設(shè)置行和列的大小,在行軌道或列軌道兩邊是網(wǎng)格線。
屬性值:
track-size: 軌道大小,可以使用css長度,百分比或用分?jǐn)?shù)(用fr單位)。
line-name: 網(wǎng)格線名字,你可以選擇任何名字。
例子:
當(dāng)你設(shè)置行或列大小為auto時,網(wǎng)格會自動分配空間和網(wǎng)格線名稱。
.container{ display:grid; grid-template-columns: 40px 50px auto 50px 40px; grid-template-rows: 25% 100px auto;}
你也可以給網(wǎng)格線定義名字,注意名字需要寫在[]里面。
.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];}
每條網(wǎng)格線可以有多個名字,例如上面行的第二條線有兩個名字,分別是row1-end和row2-start。
.container{ display:grid; grid-template-rows: [row1-start] 25% [row1-end row2-start] 25% [row2-end];}
如果你定義包含重復(fù)部分,可以使用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單位和實際值一起使用,設(shè)置fr的行或列將分(除了實際值)剩余部分。
.container{ display:grid; grid-template-columns: 1fr 50px 1fr 1fr;}
3.grid-template-areas
通過獲取網(wǎng)格項中的grid-area屬性值(名稱),來定義網(wǎng)格模版。重復(fù)網(wǎng)格區(qū)(grid-area)名稱將跨越網(wǎng)格單元格,‘.’代表空網(wǎng)格單元。
屬性值:
grid-area-name: 網(wǎng)格項的grid-area屬性值(名字)
‘.’ : 空網(wǎng)格單元
none: 不定義網(wǎng)格區(qū)域
.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"}
上面代碼示例會創(chuàng)建四列三行網(wǎng)格,第一行將是header,第二行前兩個網(wǎng)格單元是main部分、第三個為空網(wǎng)格單元、第四個為sliderbar,第三行是footer。
4. grid-column-gap:<line-size>; 和 grid-row-gap: <line-size> ;
網(wǎng)格單元間距。
屬性值:
line-size: 網(wǎng)格線間距,設(shè)置單位值。
例子:
.container{ display:grid; grid-template-columns: 100px 50px 100px; grid-template-rows: 80px auto 80px; grid-column-gap: 10px; grid-row-gap: 15px;}
注:間隔僅僅作用在網(wǎng)格單元之間,不作用在容器邊緣。
5. grid-gap:<grid-row-gap> <grid-column-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;}
注:如果只設(shè)置一個值,那么grid-column-gap 和 grid-row-gap都為那個值。
6. justify-items: start | end | center | stretch(默認(rèn)) ;
垂直于列網(wǎng)格線對齊,適用于網(wǎng)格容器里的所有網(wǎng)格項。
屬性值:
start: 左對齊。
end: 右對齊。
center: 居中對齊。
stretch: 填滿(默認(rèn))。
例子:
.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 ;
垂直于行網(wǎng)格線對齊,適用于網(wǎng)格容器里的所有網(wǎng)格項。
屬性值:
start: 頂部對齊。
end: 底部對齊。
center: 居中對齊。
stretch:填滿(默認(rèn))。
例子:
.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非彈性單位定義的話,總網(wǎng)格區(qū)域大小有可能小于網(wǎng)格容器,這時候你可以設(shè)置網(wǎng)格的對齊方式(垂直于列網(wǎng)格線對齊)。
屬性值:
start: 左對齊。
end: 右對齊。
center: 居中對齊。
stretch: 填滿網(wǎng)格容器。
space-around: 網(wǎng)格項兩邊間距相等,網(wǎng)格項之間間隔是單側(cè)的2倍。
space-between: 兩邊對齊,網(wǎng)格項之間間隔相等。
space-evenly: 網(wǎng)格項間隔相等。
例子:
.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非彈性單位定義的話,總網(wǎng)格區(qū)域大小有可能小于網(wǎng)格容器,這時候你可以設(shè)置網(wǎng)格的對齊方式(垂直于行網(wǎng)格線對齊)。
屬性值:
start: 頂部對齊。
end: 底部對齊。
center: 居中對齊。
stretch: 填滿網(wǎng)格容器。
space-around: 網(wǎng)格項兩邊間距相等,網(wǎng)格項之間間隔是單側(cè)的2倍。
space-between: 兩邊對齊,網(wǎng)格項之間間隔相等。
space-evenly: 網(wǎng)格項間隔相等。
例子:
.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> ... ;
自動生成隱式網(wǎng)格軌道(列和行),當(dāng)你定位網(wǎng)格項超出網(wǎng)格容器范圍時,將自動創(chuàng)建隱式網(wǎng)格軌道。
屬性值:
track-size: 網(wǎng)格軌道大小,可以是固定值,百分比或者是分?jǐn)?shù)(fr單位)。
為了說明隱式網(wǎng)格軌道是怎么創(chuàng)建的,我們先看下面列子:
.container{ display:grid; grid-template-columns: 60px 60px; grid-template-rows: 90px 90px}
這是2??2的網(wǎng)格,但是我們來用grid-column 和 grid-row給網(wǎng)格項定位如下:
.item-a{ grid-column: 1 / 2; grid-row: 2 / 3;}.item-b{ grid-column: 5 / 6; grid-row: 2 / 3;}
我們可以看出,網(wǎng)格項item-b定位在第五根列網(wǎng)格線(column line 5 )和第六根列網(wǎng)格線(column line 6 )之間。但是我們網(wǎng)格容器根本不存在這兩條網(wǎng)格線,所以就用兩個0寬度來填充。在這里我們可以用網(wǎng)格自動行(grid-auto-rows)和網(wǎng)格自動列(grid-auto-columns)來定義這些隱式軌道寬度。
.container{ display:grid; grid-auto-columns: 60px;}
11. grid-auto-flow : row(默認(rèn)) | column | dense ;
在沒有設(shè)置網(wǎng)格項的位置時,這個屬性控制網(wǎng)格項怎樣排列。
屬性值:
row: 按照行依次從左到右排列。
column: 按照列依次從上倒下排列。
dense: 按先后順序排列。
來看看下面結(jié)構(gòu):
<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行網(wǎng)格,同時定義grid-auto-flow:row。
.container{ display: grid; grid-template-columns: 60px 60px 60px 60px 60px; grid-template-rows: 30px 30px; grid-auto-flow: row;}
像下面布局網(wǎng)格項。
.item-a{ grid-column: 1; grid-row: 1 / 3;}.item-e{ grid-column: 5; grid-row: 1 / 3;}
由于我們設(shè)置了grid-auto-flow:row,item-b、item-c和item-d在行上是從左到右排列,如下:
如果我們設(shè)置 grid-auto-flow: column;結(jié)果如下:
12. grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [ / <grid-auto-columns>] ];
是一種簡寫形式,設(shè)置網(wǎng)格容器所有屬性。
屬性值:
none: 設(shè)置為所有屬性的默認(rèn)值。
<grid-template-rows> / <grid-template-columns>: 設(shè)置行和列的值,其他屬性為默認(rèn)值。
<grid-auto-flow> [ <grid-auto-rows> [ / <grid-auto-columns>] ] : 設(shè)置網(wǎng)格自動流、網(wǎng)格自動行、網(wǎng)格自動列的值,其他未設(shè)置則為默認(rèn)值。
例子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;}
設(shè)置在網(wǎng)格項上的屬性
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 ;
通過網(wǎng)格線來定義網(wǎng)格項的位置。grid-column-start、grid-row-start定義網(wǎng)格項的開始位置,grid-column-end、grid-row-end定義網(wǎng)格項的結(jié)束位置。
屬性值:
line: 指定帶編號或者名字的網(wǎng)格線。
span <number>: 跨越軌道的數(shù)量。
span <name>: 跨越軌道直到對應(yīng)名字的網(wǎng)格線。
auto: 自動展示位置,默認(rèn)跨度為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,默認(rèn)將跨越一個軌道。項目也可以重疊,設(shè)置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> ;
定義網(wǎng)格項名字,以便創(chuàng)建模塊(容器屬性grid-template-areas來定義模塊)。
屬性值:
name: 項目名子。
<row-start> / <column-start> / <row-end> / <column-end>: 可以是數(shù)字或網(wǎng)格線名字。
例子:
定義網(wǎng)格項名字:
.item-d{ grid-area: header}
通過網(wǎng)格線定位網(wǎng)格項:
.item-d{ grid-area: 1 / col4-start / last-line / 6 ;}
4. justify-self: justify-self: start | end | center | stretch;
定義單個網(wǎng)格項垂直于列網(wǎng)格線的對齊方式。
屬性值:
start: 網(wǎng)格區(qū)域左對齊。
end: 網(wǎng)格區(qū)域右對齊。
center: 網(wǎng)格區(qū)域居中。
stretch: 網(wǎng)格區(qū)域填滿。
例子:
.item-a{ justify-self: start;}
.item-a{ justify-self: end;}
.item-a{ justify-self: center;}
.item-a{ justify-self: stretch;}
提示:也可以在容器上設(shè)置justify-items,達(dá)到全部網(wǎng)格項對齊。
5. align-self: start | end | center | stretch;
定義單個網(wǎng)格項垂直于行網(wǎng)格線的對齊方式。
屬性值:
start: 網(wǎng)格區(qū)域頂部對齊。
end: 網(wǎng)格區(qū)域底部對齊。
center: 網(wǎng)格區(qū)域居中。
stretch: 網(wǎng)格區(qū)域填滿。
例子:
.item-a{ align-self: start;}
.item-a{ align-self: end;}
.item-a{ align-self: center;}
.item-a{ align-self: stretch;}
提示:也可以在容器上設(shè)置align-items,達(dá)到全部網(wǎng)格項對齊。