Grid 佈局又叫作網格佈局,顧名思義是一種基於二維網格的佈局方式,Grid 的強大使人興奮,讓咱們一塊兒來走進 Grid 的世界吧。css
好了,你們都坐好,我準備發車啦。不符合要求的同窗請下車,沒滿 18 歲的,咳咳,開玩笑。不是全部人如今都能搭上 Grid 的小車車,畢竟項目兼容性問題很現實,不過不耽誤咱們學習。html
我替你們翻譯一下上面的瀏覽器都是啥,順序從左到右:css3
好了,你們看了看瀏覽器的兼容性就知道,現在主流瀏覽器都已經支持了 Grid 佈局,還等啥呢?上車吧。git
乘客們,在開始瞭解用法以前,咱們要了解一些 Grid 佈局的基本概念,我想你們應該小時候都用過一種叫小字本的東西,這就是個正兒八經的網格。github
display: grid;
就將一個容器變成了網格容器,就好比說上面小字本里外層的那個綠框。好了,基本概念瞭解的差很少了,咱們去往下一站。segmentfault
第二站到了,咱們要繼續吹牛了。api
本站要介紹的 api:瀏覽器
grid-template-columns
和 grid-template-rows
grid-gap
-> grid-row-gap
+ grid-column-gap
第一件事,掏出代碼:markdown
<div class="container"> <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <div>6</div> </div> 複製代碼
body { background: #CCCCCC; } .container > div { font-size: 35px; font-weight: bold; color: #fff; text-align: center; background: #666666; } .container > div:nth-child(2n) { background: #336666; } .container > div:nth-child(4n) { background: #f37e70; } .container { display: grid; grid-template-columns: 120px 120px 120px; grid-template-rows: 50px 50px; } 複製代碼
好了,如今它長這個樣子。ide
咱們能夠看出上面一些關鍵的 css 代碼:
display: grid;
將外層容器變成一個網格佈局容器。grid-template-columns: 120px 120px 120px;
將容器畫成 3 列,每列 120px;grid-template-rows: 50px 50px;
畫成 2 行,每行 50px。上面兩個 api 給網格加上了兩條橫線,三條豎線,把容器畫成了一個個的格子。而後將網格項一個一個填進去,那麼聰明的同窗又會想了,你這樣畫好格子,裏面有 6 個格子,那我再添一個 div 會出現什麼狀況?好吧,知足這位同窗的好奇心,咱們加一個 div 進去。
而後就會變成這樣:
神奇,是否是,明明俺就畫了 6 個格子,竟然 7 出現了,而且還有必定高度。其實在 grid 裏,它有一個隱式網格軌道。
當咱們的網格項處於咱們沒有定義的網格部分的時候,它會有一個默認的值,咱們也能夠選擇去定義隱式網格軌道的大小,經過 grid-auto-rows
和 grid-auto-columns
來定義行和列,關於這部分要說的話不少,你們能夠到這個博客去了解。
講完這個,咱們再看看,每一個格子捱得太近了,一點都不美觀,咋辦呢?咱們加上 grid-gap: 2px 4px;
看看:
能夠看到,使用這個屬性咱們定了網格的間隙,這個 api 實際上是兩個 api 的組合(grid-column-gap
和 grid-row-gap
)。
好了,這一站就是基本用法,下面咱們繼續發車啦。
上面咱們經過一些基礎的屬性,寫了一個 6 個格子的頁面。這一節咱們不講屬性,講一下在 grid 中的一個單位值 — fr。那麼這個 fr,表明的是什麼意思呢?在 flex 中也有相似的屬性,fr 的意思就是在自由空間進行分配的一個單位,那麼是什麼意思呢?
好比說,容器寬度爲 1000px,如今假如 grid-template-columns: 200px 1fr 1fr 2fr
。那麼這就表示分了 4 列,第一列爲 200px,而後剩下的 800px 就是自由空間了,通過計算能夠得出 1fr 爲 200px,這就是 fr 的意義。
那麼,咱們上面的例子其實能夠這樣寫 grid-template-columns: 1fr 1fr 1fr;
。可是如今又出現了一個問題,這個 1fr 寫的好煩,能不能就寫一個。
好消息,是有的,咱們可使用 repeat 來簡寫,因而上面的例子又能夠改爲 grid-template-columns: repeat(3, 1fr)
。
說完這兩個,咱們繼續下一站。
這一站咱們要說這些 api:
grid-column
-> grid-column-start
+ grid-column-end
grid-row
-> grid-row-start
+ grid-row-end
好了咱們拋棄上面的例子,如今假如咱們接到一個需求,咱們要使用 3 欄佈局,左右固定 200px,中間自適應,咋辦呢?相信你們一下就想到了,畢竟你們都很聰明。
<div class="container"> <div>Left</div> <div>Main</div> <div>Right</div> </div> 複製代碼
// ...,跟上面相同的代碼
.container {
display: grid;
grid-template-columns: 200px 1fr 200px;
grid-template-rows: 500px;
grid-gap: 2px 4px;
}
複製代碼
好了,如今咱們是這樣的:
需求又來了,咱們要加上一個 header 和一個 footer,寬度是 main 的寬度,如今又怎麼辦呢?首先 container 須要改:
.container { display: grid; grid-template-columns: 200px 1fr 200px; grid-template-rows: 100px 500px 100px; grid-gap: 2px 4px; } 複製代碼
如今咱們能夠用網格線來進行佈局了,在上面的網格佈局中橫向有 4 條網格線,豎向有 4 條網格線,默認網格會爲編號,從 1 開始,因而咱們能夠用網格線將元素固定到它應該在的位置:
/* 類名就是 html 對應的 div */ .left { grid-column: 1 / 2; } .main { grid-column: 2 / -2; } .right { grid-column: -2 / -1; } .header { grid-column: 2 / -2; } .footer { grid-column: 2 / -2; } 複製代碼
這樣的話,咱們的佈局就成了這樣子:
在上面有一個小技巧,若是中間線比較多,你要選擇比較靠後的線,就可使用負數來進行選擇。
上面的 1 和 2 的使用是差很少的,這裏就不詳述了。
注意,你能夠給網格線取一些語義化的名字便於你使用,好比下面這樣,footer 同樣能夠和 main 等寬:
<div class="container"> <div class="left">Left</div> <div class="main">Main</div> <div class="right">Right</div> <div class="footer">Footer</div> </div> 複製代碼
.container { display: grid; grid-template-columns: 200px [main-start] 1fr [main-end] 200px; grid-template-rows: 200px 200px; grid-gap: 2px 4px; } .footer { grid-column: main-start / main-end; } 複製代碼
咱們能夠給網格線取名字,而後再去使用它。
這節介紹的 api:
咱們能夠經過另外一種建立網格的方式來定位元素,就如同畫圖同樣,就那上面那個有 header 和 footer 的例子來講,咱們能夠這麼寫:
.container { display: grid; grid-template-columns: 200px 1fr 200px; grid-template-rows: 50px 300px 50px; grid-template-areas: ". h ." "l m r" ". f ."; grid-gap: 2px 4px; } .header { grid-area: h; } .left { grid-area: l; } .right { grid-area: r; } .main { grid-area: m; } .footer { grid-area: f; } 複製代碼
經過這樣的方式,咱們同樣能作到上面的那種定位操做,注意的是在 grid-template-areas
中 . 表明的是這個位置空着。
在上面,咱們說過一種 repeat 的簡單用法,建立網格時重複指定的次數,可是有的時候咱們並不想指定次數,而是但願自動填充,這時候怎麼辦呢?
這時候咱們就要提到 auto-fit
和 auto-fill
了。
首先,咱們經過 repeat 先把格子建出來:
.container { display: grid; grid-template-columns: repeat(9, 1fr); grid-template-rows: 50px; grid-gap: 2px 4px; } 複製代碼
這樣咱們就建立了一個基於 9 列的網格系統,若是咱們的視窗不斷變小,那麼咱們的每一格也會相應的變窄,咱們不但願它變得很是窄,咋辦呢?
Grid 有一個 minmax() 函數可使用,這個函數接收兩個參數,一個最小值,一個最大值,當瀏覽器窗口發生改變的時候,它可以保證該元素是在這個範圍以內改變。好比說:
.container{ grid-template-columns: repeat(9, minmax(250px, 1fr)); } 複製代碼
當咱們把 grid-template-columns
變成這樣以後,每一列的寬度都會在 250px 到 1fr 之間,可是咱們會發現,他裝不下這些格子,可是它也沒有換行,由於你告訴它有 9 列,因而出現了滾動條,可是你不但願出現這東西,咋辦呢?
這時候就到了咱們上面說的兩個參數出場的時候到了。
.container{ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); } 複製代碼
當咱們加上這個參數事後,就會讓瀏覽器去處理列寬和換行的問題,若是你給的容器寬度不夠,它就會換行。
那麼 fit 和 fill 有啥區別呢?我找了一些資料,裏面有兩句總結是這麼說的:
auto-fill
傾向於容納更多的列,因此若是在知足寬度限制的前提下還有空間能容納新列,那麼它會暗中建立一些列來填充當前行。即便建立出來的列沒有任何內容,但實際上仍是佔據了行的空間。
auto-fit
傾向於使用最少列數佔滿當前行空間,瀏覽器先是和 auto-fill 同樣,暗中建立一些列來填充多出來的行空間,而後坍縮(collapse)這些列以便騰出空間讓其他列擴張。
作一個實驗,當寬度足夠大時,這二者區別就出來了:
.container1{ grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); } .container2{ grid-template-columns: repeat(auto-fit, minmax(40px, 1fr)); } 複製代碼
這樣能夠看出區別了,fill 是儘量多容納列,它會本身造一些列來填充剩餘空間,其實它是鋪滿了的,只是你看不見而已,而 fit 是擴張原有列來鋪滿這一行。
至於具體詳細的解釋,你們能夠去這篇譯文看一看,說得很是詳細了。
好了,關於 grid 大概就說這麼多了,其實關於這些 api 的使用還有不少的參數問題,這裏沒有細說,只是讓你們知道 grid 能幹嗎,至於詳細的說明,能夠去下面幾個博客看一看。
另外還有一些屬性沒有介紹,是關於對齊等屬性,你們在有需求的時候能夠去下面的資料找到。
更多資料:
若是各位看官看的還行,能夠到 個人博客倉庫 裏給我一顆小小的 star 支持一下,不勝感激。