CSS網格佈局是瀏覽器Flexbox佈局以後最重要的佈局方式。咱們能夠忘記過去15年常用的的各類「神奇數字」,hacks和一系列變通佈局方案。網格佈局提供了很是簡單的聲明佈局方式,以後不再須要藉助一些常見的主流css框架,也能減小不少手動實現的佈局方式css
若是你之前不熟悉CSS網格佈局,那麼你能夠開始瞭解它了。它是一種適用於容器元素,並能指定子元素的間距、大小和對齊方式的佈局工具。html
CSS網格佈局賦予咱們更強大的能力——你們熟悉的水平垂直居中佈局,不須要增長標籤就能作到。一樣,這也能讓咱們不須要媒體查詢就能根據可用空間自動適應。前端
首先網格佈局有很多新語法須要學習,可是你只須要稍微看下就能上手。本文將會用示例帶你學習CSS網格佈局各類各樣重要的入門概念。git
CSS網格佈局從Safari 10.1, Firefox 52, Opera 44, Chrome 57開始收到支持,微軟Edge在Edge 15會更新對網格佈局的支持。github
微軟的瀏覽器(IE10–11和Edge 13-14)有一種比較舊的實現,因此有很多限制,咱們會簡單介紹新的實現方式和老的實現方式之間的區別,這樣你能知道如何規避他們。瀏覽器
對於大多數佈局,咱們會使用下面的query特性來讓老的瀏覽器對他們理解的特性也能工做:bash
@supports (display: grid) {
.grid {
display: grid;
}
}複製代碼
不支持瀏覽器@supports
或網格的瀏覽器將不會生效。app
爲了能正確展現文中的示例,你須要使用支持網格佈局的瀏覽器。框架
爲了演示CSS網格佈局如何定義列,咱們從下面的佈局開始:
模塊化
爲了建立上述網格佈局,咱們須要使用grid-template-columns
和grid-gap
。grid-template-columns
表示網格中的列是如何佈局的,它的值是一連串以空格分割的的值,這些值標識每列的大小,值的個數表示列的數目。
例如,四列250px寬度的網格佈局能夠這樣表示:
grid-template-columns: 250px 250px 250px 250px;複製代碼
也可使用repeat
關鍵字表示:
grid-template-columns: repeat(4, 250px);複製代碼
grid-gap
定義了網格佈局的間距大小,接收一個或兩個值,若是定義兩個值則表示列(column)和行(row)的間距大小。
在兩列布局示例中,咱們能夠以下使用:
.grid {
display: grid;
grid-template-columns: 50vw 50vw;
grid-gap: 1rem;
}複製代碼
不幸的是,這個間距將會佔用容器元素的總體寬度,計算出來就是100vw + 1rem
,最終這個佈局會致使出現水平滾動條。
爲了解決這個空間溢出問題,咱們須要些不一樣的方法來處理,須要用分數單位或者說是FR。
分數單位標識佔用可用空間的份額,若是900px是可用空間,其中的一個元素佔有1份,另外的元素佔有2份——那麼第一個元素的寬度會是900px的1/3,另外的元素是900px的2/3。
修改後用分數代替view-port單位的新代碼以下:
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1rem;
}複製代碼
爲了對齊示例中的內容,咱們在子元素上使用grid佈局,並加上對齊屬性來定位他們到指定軌道(track),軌道就是一個網格的列或行的某個位置的常見的名稱。網格跟Flex佈局同樣,有一系列對齊的屬性——共有四種值——start
, center
, end
, 和stretch
,分別對應其子元素所在的軌道。stretch
跟其餘不太同樣,它會將元素從所在軌道的頭拉伸到尾。
[align-items 和 justify-content]
例子中咱們要將內容水平和垂直居中,能夠經過在容器上設置下面這些屬性:
.center-content {
display: grid;
align-items: center;
justify-content: center;
}複製代碼
若是使用舊的網格佈局方式建立,咱們須要考慮實現中的諸多限制。舊的佈局方式不只沒有grid-gap
,並且你須要在每個網格元素上聲明網格元素的起始位置,不然默認會設置爲1,這樣全部的網格都會堆在第一列。
舊版本的佈局方式須要經過增長間距做爲網格軌道的一部分,也須要設置每一個網格從哪裏開始:
.grid-legacy {
display: -ms-grid;
-ms-grid-columns: 1fr 1rem 1fr; // 取代 gap 間距
}
.grid-legacy:first-child {
-ms-grid-column: 1;
}
.grid-legacy:last-child {
-ms-grid-column: 3;
}複製代碼
舊的佈局方式跟IE 11中Flexbox有同樣的問題,在容器上設置最小高度(min-height)不必定會生效。這個問題經過網格佈局來解決更方便。
爲了實現這個效果咱們在父容器的行屬性上使用minmax
方法,minmax
指定了行或列的最大和最小值。
-ms-grid-rows: minmax(100vh, 1fr);複製代碼
在子元素上咱們聲明一個單位爲1fr的單列單行的網格:
.ms-cell {
-ms-grid-columns: 1fr;
-ms-grid-rows: 1fr;
}複製代碼
最後,由於咱們不能像Flexbox或最新網格佈局那樣根據父元素對齊,咱們必須使用元素自身的對齊方式來對齊:
.ms-align-center {
-ms-grid-column: 1;
-ms-grid-column-align: center; // 新型grid佈局中的 align-self
-ms-grid-row-align: center; // 新型grid佈局中的 justify-self
}複製代碼
到此咱們實現瞭如何建立列、實現間距、內容對齊及對舊的網格佈局的支持。接下來讓咱們實驗下如何經過grid實現內邊距。
網格佈局容許你經過grid-column-start
屬性指定列開始的位置,因此就有了能夠在網格內建立內邊距的可能性。
建立內邊距的一種方式是在列的實際位置上設置一個數字,空出網格元素的原始空間, 網格元素也會被push到新的網格列。
在上面的內邊距示例中,html結構中用一個div包裹另一個div:
<div class="grid">
<div class="child"><!-- 內容 --></div>
</div複製代碼
網格像這樣設置:
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
}複製代碼
爲了讓子元素從右側開始,咱們設置子元素從第2列開始:
.child {
grid-column-start: 2;
}複製代碼
注意:在Firefox 52中的一個差別致使一個垂直對齊問題——基於FR單位的行不會拉伸得跟整個窗口同樣高。爲了解決(address)這個問題咱們設置子元素爲網格項,並給每一行設置一個想要的高度:
.l-grid--full-height {
grid-template-rows: minmax(100vh, 1fr);
}複製代碼
在四列布局中,給原本在第三列的網格項上設置grid-column-start:2;
,那麼會找到下一個可用的第二列來填充空間。
網格軌道會跳過某些列,直到找到下一列。咱們能夠利用這個方法在網格內建立空白,沒有內容的網格也會被分配。
[建立空白示例]
若是咱們想分割佈局爲四份,咱們目前所瞭解的關於列的佈局方式對行一樣有效:
.grid {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 250px 250px;
}複製代碼
理想狀況下這個示例是沒問題的。由於此時每一個網格項的內容足夠少而不會撐開每行。但隨着內容的變化,一切都不同了。當示例中的內容超出指定行的大小後,看下會發生什麼:
咱們建立了250px高的兩行,若是內容超過每行的高度,將會打破布局並和後面的行的內容重疊。並非一個咱們想要的結果。
咱們在該場景下須要的是設置最小尺寸的能力,但又要容許尺寸能夠根據內容彈性變化。這裏咱們經過上面舊瀏覽器示例中的minmax
關鍵字實現。
.grid {
grid-template-rows: minmax(250px, auto) minmax(250px, auto);
}複製代碼
如今咱們已經瞭解了建立帶有內容的行的基礎方法,咱們開始來建立水平和垂直交錯的更復雜網格佈局。
咱們開始建立更復雜的網格佈局。將網格中的每一個網格項設置成佔據多條軌道,在一列內,咱們能經過grid-column-start
和grid-column-end
實現,或者經過以下所示更簡單的寫法:
grid-column: 1 / 3;複製代碼
用這種實現方式的弊端是難以「模塊化」,爲了定位每塊內容須要寫不少代碼。span關鍵字更符合模塊化的思路,由於咱們能放在任何地方,讓網格來控制他。咱們能夠定義網格項的開始位置,及其佔據的軌道數:
.span-column-3 {
grid-column-start: span 3;
}複製代碼
任何添加該class的網格將會從其開始位置,佔據三個軌道。
咱們能設計一個多軌道佈局,經過將佈局分解爲grid佈局中的最小單元。本示例中的最小單位是圖中高亮的部分。
圍繞最小單位,咱們能靈活的使用span來建立一些有意思的佈局,由於span是能夠疊加的——你能夠結合列和行的軌道在網格中建立多層級。
雖然上面說到的例子能在可用空間內適應變化,可是沒有一個是專門爲空間變化設計的。網格有兩個很是有用的特性來適應可用空間的變化。這兩個屬性叫‘auto-fit’和‘auto-fill’,像下面這樣結合repeat function和minmax function使用:
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));複製代碼
這些值代替了repeat中的數字,並計算在每條軌道上會填充多少行或列。兩者之間最大不一樣是當一條軌道上空白的溢出時的他們的處理方式不一樣。
auto-fit
嘗試在不致使列溢出的狀況下,放置該列能處理的最大數量的重複元素。當沒有足夠的空間來放置更多的元素時,以後的元素將會放到下一行,不能填滿的空間將會被保留。
auto-fill
的表現跟auto-fit
相似,可是任何的空白空間都會自動收縮,同時這一行的元素也會被拉昇——相似flexbox的效果,列會隨着可用空間變小發生摺疊。
[grid-auto-fit示例]
依賴媒體查詢的佈局跟窗口大小關係很大,這不夠模塊化——系統內的組件應該能根據可用空間自適應。那麼在實踐中會是什麼樣的呢?
咱們已經經歷了快十五年的CSS浮動爲主的佈局方式,咱們上面學習了幾乎全部你能用float實現的佈局——CSS網格佈局是這個領域的新表明,仍然還有許多東西須要去嘗試和學習。
如今最重要的步驟是開始使用它。在構建、建立更多高級佈局的時候會很方便。網格佈局還有很多未知領域,一旦咱們更好地理解其能力並開始與其餘特性結合,咱們便能用更少代碼創造更多有趣、靈活的佈局,並能減小些框架抽象的麻煩。
若是你感興趣並想進一步探究CSS網格,能夠試下Rachel Andrew的例子,這裏面經過帶解釋說明的實例探討了CSS網格佈局的每個特性。
iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、噹噹開售。