Grid 佈局發車啦

Grid 佈局又叫作網格佈局,顧名思義是一種基於二維網格的佈局方式,Grid 的強大使人興奮,讓咱們一塊兒來走進 Grid 的世界吧。css

兼容性

好了,你們都坐好,我準備發車啦。不符合要求的同窗請下車,沒滿 18 歲的,咳咳,開玩笑。不是全部人如今都能搭上 Grid 的小車車,畢竟項目兼容性問題很現實,不過不耽誤咱們學習。html

兼容性

我替你們翻譯一下上面的瀏覽器都是啥,順序從左到右:css3

  • PC 端: Chrome、Edge、Firefox、IE、Opera、Safari
  • 移動端: Android、Chrome for Android、Edge Mobile、Firefox for Android、Opera、IOS Safari、Samsung Internet

好了,你們看了看瀏覽器的兼容性就知道,現在主流瀏覽器都已經支持了 Grid 佈局,還等啥呢?上車吧。git

基本概念

乘客們,在開始瞭解用法以前,咱們要了解一些 Grid 佈局的基本概念,我想你們應該小時候都用過一種叫小字本的東西,這就是個正兒八經的網格。github

小字本

  • Container: 網格容器,當咱們設置 display: grid; 就將一個容器變成了網格容器,就好比說上面小字本里外層的那個綠框。
  • Item: 網格項,在咱們設置的網格容器中的每個子元素都是網格項。
  • Line: 網格線,顧名思義啦,這東西就是網格之間分界的線,就上小字本里的橫着豎着的線。
  • Track: 網格軌道,兩條相鄰的網格線之間的空間,也就是網格的行或列。
  • Cell: 網格單元,兩個相鄰的行和列之間的區域,也就像是小字本里的每一個小格子了。
  • Area: 網格區域,四條網格線包圍起來的區域。

好了,基本概念瞭解的差很少了,咱們去往下一站。segmentfault

基本用法

第二站到了,咱們要繼續吹牛了。api

本站要介紹的 api:瀏覽器

  1. grid-template-columnsgrid-template-rows
  2. 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 代碼:

  1. 使用 display: grid; 將外層容器變成一個網格佈局容器。
  2. 如今咱們擁有了一個容器,咱們如今要開始幹什麼了?對,沒錯,咱們要開始把這個容器畫成一個一個的格子。
  3. grid-template-columns: 120px 120px 120px; 將容器畫成 3 列,每列 120px;grid-template-rows: 50px 50px; 畫成 2 行,每行 50px。

上面兩個 api 給網格加上了兩條橫線,三條豎線,把容器畫成了一個個的格子。而後將網格項一個一個填進去,那麼聰明的同窗又會想了,你這樣畫好格子,裏面有 6 個格子,那我再添一個 div 會出現什麼狀況?好吧,知足這位同窗的好奇心,咱們加一個 div 進去。

而後就會變成這樣:

神奇,是否是,明明俺就畫了 6 個格子,竟然 7 出現了,而且還有必定高度。其實在 grid 裏,它有一個隱式網格軌道。

當咱們的網格項處於咱們沒有定義的網格部分的時候,它會有一個默認的值,咱們也能夠選擇去定義隱式網格軌道的大小,經過 grid-auto-rowsgrid-auto-columns 來定義行和列,關於這部分要說的話不少,你們能夠到這個博客去了解。

講完這個,咱們再看看,每一個格子捱得太近了,一點都不美觀,咋辦呢?咱們加上 grid-gap: 2px 4px; 看看:

能夠看到,使用這個屬性咱們定了網格的間隙,這個 api 實際上是兩個 api 的組合(grid-column-gapgrid-row-gap)。

好了,這一站就是基本用法,下面咱們繼續發車啦。

fr 單位以及 repeat

上面咱們經過一些基礎的屬性,寫了一個 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:

  1. grid-column -> grid-column-start + grid-column-end
  2. 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:

  1. grid-template-areas
  2. grid-area

咱們能夠經過另外一種建立網格的方式來定位元素,就如同畫圖同樣,就那上面那個有 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 進階

在上面,咱們說過一種 repeat 的簡單用法,建立網格時重複指定的次數,可是有的時候咱們並不想指定次數,而是但願自動填充,這時候怎麼辦呢?

這時候咱們就要提到 auto-fitauto-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 支持一下,不勝感激。

相關文章
相關標籤/搜索