最強大的 CSS 佈局 —— Grid 佈局

Grid 佈局是什麼?

Grid 佈局即網格佈局,是一種新的 CSS 佈局模型,比較擅長將一個頁面劃分爲幾個主要區域,以及定義這些區域的大小、位置、層次等關係。號稱是最強大的的 CSS 佈局方案,是目前惟一一種 CSS 二維佈局。利用 Grid 佈局,咱們能夠輕鬆實現相似下圖佈局,演示地址css

Grid 佈局和 flex 佈局

講到佈局,咱們就會想到 flex 佈局,甚至有人認爲居然有 flex 佈局了,彷佛沒有必要去了解 Grid 佈局。但 flex 佈局和 Grid 佈局有實質的區別,那就是 flex 佈局是一維佈局,Grid 佈局是二維佈局flex 佈局一次只能處理一個維度上的元素佈局,一行或者一列。Grid 佈局是將容器劃分紅了「行」和「列」,產生了一個個的網格,咱們能夠將網格元素放在與這些行和列相關的位置上,從而達到咱們佈局的目的。html

Grid 佈局遠比 flex 佈局強大!前端

flex佈局示例:算法

Grid 佈局示例:瀏覽器

Grid 佈局

Grid 的一些基礎概念

咱們使用 Grid 實現一個小例子,演示 Grid 的一些基礎概念,演示地址bash

<div class="wrapper">
  <div class="one item">One</div>
  <div class="two item">Two</div>
  <div class="three item">Three</div>
  <div class="four item">Four</div>
  <div class="five item">Five</div>
  <div class="six item">Six</div>
</div>
複製代碼
.wrapper {
  margin: 60px;
  /* 聲明一個容器 */
  display: grid;
  /* 聲明列的寬度 */
  grid-template-columns: repeat(3, 200px);
  /* 聲明行間距和列間距 */
  grid-gap: 20px;
  /* 聲明行的高度 */
  grid-template-rows: 100px 200px;
}
.one {
  background: #19CAAD;
}
.two { 
  background: #8CC7B5;
}
.three {
  background: #D1BA74;
}
.four {
  background: #BEE7E9;
}
.five {
  background: #E6CEAC;
}
.six {
  background: #ECAD9E;
}
.item {
  text-align: center;
  font-size: 200%;
  color: #fff;
}
複製代碼

容器和項目:咱們經過在元素上聲明 display:griddisplay:inline-grid 來建立一個網格容器。一旦咱們這樣作,這個元素的全部直系子元素將成爲網格項目。好比上面 .wrapper 所在的元素爲一個網格容器,其直系子元素將成爲網格項目。app

網格軌道:grid-template-columnsgrid-template-rows 屬性來定義網格中的行和列。容器內部的水平區域稱爲行,垂直區域稱爲列。上圖中 OneTwoThree 組成了一行,OneFour 則是一列ide

行和列

網格單元:一個網格單元是在一個網格元素中最小的單位, 從概念上來說其實它和表格的一個單元格很像。上圖中 OneTwoThreeFour...都是一個個的網格單元函數

網格線:劃分網格的線,稱爲"網格線"。應該注意的是,當咱們定義網格時,咱們定義的是網格軌道,而不是網格線。Grid 會爲咱們建立編號的網格線來讓咱們來定位每個網格元素。m 列有 m + 1 根垂直的網格線,n 行有 n + 1 跟水平網格線。好比上圖示例中就有 4 根垂直網格線。通常而言,是從左到右,從上到下,1,2,3 進行編號排序。固然也能夠從右到左,從下到上,按照 -1,-2,-3...順序進行編號排序佈局

網格線

容器屬性介紹

Grid 佈局相關的屬性以及值衆多,須要記憶的很多,建議能夠跟 demo 一塊兒結合起來,邊敲代碼邊理解,再利用一些空閒時間記憶一下。筆者會在介紹每一個屬性的時候,作個小 demo 演示,建議你們能夠本身修改看看效果加深記憶

Grid 佈局屬性能夠分爲兩大類,一類是容器屬性,一類是項目屬性。咱們先來看容器屬性

display 屬性

display 屬性演示

咱們經過在元素上聲明 display:griddisplay:inline-grid 來建立一個網格容器。聲明 display:grid 則該容器是一個塊級元素,設置成 display: inline-grid 則容器元素爲行內元素

.wrapper {
  display: grid;
}
複製代碼

塊級元素

.wrapper-1 {
  display: inline-grid;
}
複製代碼

行內屬性

grid-template-columns 屬性和 grid-template-rows 屬性

grid-template-columns 和 grid-template-rows 屬性演示地址

grid-template-columns 屬性設置列寬,grid-template-rows 屬性設置行高,這兩個屬性在 Grid 佈局中尤其重要,它們的值是有多種多樣的,並且它們的設置是比較類似的,下面針對 grid-template-columns 屬性進行講解

固定的列寬和行高

.wrapper {
  display: grid;
  /* 聲明瞭三列,寬度分別爲 200px 100px 200px */
  grid-template-columns: 200px 100px 200px;
  grid-gap: 5px;
  /* 聲明瞭兩行,行高分別爲 50px 50px */
  grid-template-rows: 50px 50px;
}
複製代碼

以上表示固定列寬爲 200px 100px 200px,行高爲 50px 50px

固定行高和列寬

repeat() 函數:能夠簡化重複的值。該函數接受兩個參數,第一個參數是重複的次數,第二個參數是所要重複的值。好比上面行高都是同樣的,咱們能夠這麼去實現,實際效果是如出一轍的

.wrapper-1 {
  display: grid;
  grid-template-columns: 200px 100px 200px;
  grid-gap: 5px;
  /*  2行,並且行高都爲 50px  */
  grid-template-rows: repeat(2, 50px);
}
複製代碼

auto-fill 關鍵字:表示自動填充,讓一行(或者一列)中儘量的容納更多的單元格。grid-template-columns: repeat(auto-fill, 200px) 表示列寬是 200 px,但列的數量是不固定的,只要瀏覽器可以容納得下,就能夠放置元素,代碼以及效果以下圖所示:

.wrapper-2 {
  display: grid;
  grid-template-columns: repeat(auto-fill, 200px);
  grid-gap: 5px;
  grid-auto-rows: 50px;
}
複製代碼

image

fr 關鍵字Grid 佈局還引入了一個另外的長度單位來幫助咱們建立靈活的網格軌道。fr 單位表明網格容器中可用空間的一等份。grid-template-columns: 200px 1fr 2fr 表示第一個列寬設置爲 200px,後面剩餘的寬度分爲兩部分,寬度分別爲剩餘寬度的 1/3 和 2/3。代碼以及效果以下圖所示:

.wrapper-3 {
  display: grid;
  grid-template-columns: 200px 1fr 2fr;
  grid-gap: 5px;
  grid-auto-rows: 50px;
}
複製代碼

image

minmax() 函數:咱們有時候想給網格元素一個最小和最大的尺寸,minmax() 函數產生一個長度範圍,表示長度就在這個範圍之中均可以應用到網格項目中。它接受兩個參數,分別爲最小值和最大值。grid-template-columns: 1fr 1fr minmax(300px, 2fr) 的意思是,第三個列寬最少也是要 300px,可是最大不能大於第一第二列寬的兩倍。代碼以及效果以下:

.wrapper-4 {
  display: grid;
  grid-template-columns: 1fr 1fr minmax(300px, 2fr);
  grid-gap: 5px;
  grid-auto-rows: 50px;
}
複製代碼

image

auto 關鍵字:由瀏覽器決定長度。經過 auto 關鍵字,咱們能夠輕易實現三列或者兩列布局。grid-template-columns: 100px auto 100px 表示第一第三列爲 100px,中間由瀏覽器決定長度,代碼以及效果以下:

.wrapper-5 {
  display: grid;
  grid-template-columns: 100px auto 100px;
  grid-gap: 5px;
  grid-auto-rows: 50px;
}
複製代碼

image

grid-row-gap 屬性、grid-column-gap 屬性以及 grid-gap 屬性

grid-row-gap 屬性、grid-column-gap 屬性以及 grid-gap 屬性演示地址

grid-row-gap 屬性、grid-column-gap 屬性分別設置行間距和列間距。grid-gap 屬性是二者的簡寫形式。

grid-row-gap: 10px 表示行間距是 10px,grid-column-gap: 20px 表示列間距是 20px。grid-gap: 10px 20px 實現的效果是同樣的

.wrapper {
  display: grid;
  grid-template-columns: 200px 100px 100px;
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}
複製代碼
.wrapper-1 {
  display: grid;
  grid-template-columns: 200px 100px 100px;
  grid-auto-rows: 50px;
  grid-row-gap: 10px;
  grid-column-gap: 20px;
}
複製代碼

以上兩種寫法效果是同樣的。

grid-template-areas 屬性

grid-area 以及 grid-template-areas演示地址

grid-template-areas 屬性用於定義區域,一個區域由一個或者多個單元格組成

通常這個屬性跟網格元素的 grid-area 一塊兒使用,咱們在這裏一塊兒介紹。 grid-area 屬性指定項目放在哪個區域

.wrapper {
  display: grid;
  grid-gap: 10px;
  grid-template-columns: 120px  120px  120px;
  grid-template-areas:
    ". header header"
    "sidebar content content";
  background-color: #fff;
  color: #444;
}
複製代碼

上面代碼表示劃分出 6 個單元格,其中值得注意的是 . 符號表明空的單元格,也就是沒有用到該單元格。

.sidebar {
  grid-area: sidebar;
}

.content {
  grid-area: content;
}

.header {
  grid-area: header;
}
複製代碼

以上代碼表示將類 .sidebar .content .header所在的元素放在上面 grid-template-areas 中定義的 sidebar content header 區域中

grid-auto-flow 屬性

grid-auto-flow 屬性演示地址

grid-auto-flow 屬性控制着自動佈局算法怎樣運做,精確指定在網格中被自動佈局的元素怎樣排列。默認的放置順序是"先行後列",即先填滿第一行,再開始放入第二行,即下圖英文數字的順序 one,two,three...。這個順序由 grid-auto-flow 屬性決定,默認值是 row

.wrapper {
  display: grid;
  grid-template-columns: 100px 200px 100px;
  grid-auto-flow: row;
  grid-gap: 5px;
  grid-auto-rows: 50px;
}
複製代碼

細心的同窗可能發現了一個問題,就是第五個項目和第六個項目之間有個空白(以下圖所示),這個是因爲第六塊的長度大於了空白處的長度,被擠到了下一行致使的。在實際應用中,咱們可能想讓下面長度合適的填滿這個空白,這個時候能夠設置 grid-auto-flow: row dense,表示儘量填滿表格。代碼以及效果以下所示:

image

.wrapper-2 {
  display: grid;
  grid-template-columns: 100px 200px 100px;
  grid-auto-flow: row dense;
  grid-gap: 5px;
  grid-auto-rows: 50px;
}
複製代碼

image

能夠設置 grid-auto-flow: column,表示先列後行,代碼以及效果以下圖所示:

.wrapper-1 {
  display: grid;
  grid-auto-columns: 100px;
  grid-auto-flow: column;
  grid-gap: 5px;
  grid-template-rows:  50px 50px;
}
複製代碼

image

justify-items 屬性、align-items 屬性以及 place-items 屬性

justify-items 屬性、align-items 屬性演示地址

justify-items 屬性設置單元格內容的水平位置(左中右),align-items 屬性設置單元格的垂直位置(上中下)

下面以 justify-items 屬性爲例進行講解,align-items 屬性同理,只是方向爲垂直方向。它們都有以下屬性:

.container {
  justify-items: start | end | center | stretch;
  align-items: start | end | center | stretch;
}
複製代碼

其代碼實現以及效果以下:

.wrapper, .wrapper-1, .wrapper-2, .wrapper-3 {
  display: grid;
  grid-template-columns: 100px 200px 100px;
  grid-gap: 5px;
  grid-auto-rows: 50px;
  justify-items: start;
}
.wrapper-1 {
  justify-items: end;
}
.wrapper-2 {
  justify-items: center;
}
.wrapper-3 {
  justify-items: stretch;
}
複製代碼
  • start:對齊單元格的起始邊緣

image

  • end:對齊單元格的結束邊緣

image

  • center:單元格內部居中

image

  • stretch:拉伸,佔滿單元格的整個寬度(默認值)

image

justify-content 屬性、align-content 屬性以及 place-content 屬性

justify-content 屬性、align-content 屬性演示地址

justify-content 屬性是整個內容區域在容器裏面的水平位置(左中右),align-content 屬性是整個內容區域的垂直位置(上中下)。它們都有以下的屬性值。

.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}
複製代碼

下面以 justify-content 屬性爲例進行講解,align-content 屬性同理,只是方向爲垂直方向

  • start - 對齊容器的起始邊框
  • end - 對齊容器的結束邊框
  • center - 容器內部居中
.wrapper, .wrapper-1, .wrapper-2, .wrapper-3, .wrapper-4, .wrapper-5, .wrapper-6 {
  display: grid;
  grid-template-columns: 100px 200px 100px;
  grid-gap: 5px;
  grid-auto-rows: 50px;
  justify-content: start;
}
.wrapper-1 {
  justify-content: end;
}
.wrapper-2 {
  justify-content: center;
}
複製代碼

image

  • space-around - 每一個項目兩側的間隔相等。因此,項目之間的間隔比項目與容器邊框的間隔大一倍
  • space-between - 項目與項目的間隔相等,項目與容器邊框之間沒有間隔
  • space-evenly - 項目與項目的間隔相等,項目與容器邊框之間也是一樣長度的間隔
  • stretch - 項目大小沒有指定時,拉伸佔據整個網格容器
.wrapper-3 {
  justify-content: space-around;
}
.wrapper-4 {
  justify-content: space-between;
}
.wrapper-5 {
  justify-content: space-evenly;
}
.wrapper-6 {
  justify-content: stretch;
}
複製代碼

image

grid-auto-columns 屬性和 grid-auto-rows 屬性

grid-auto-columns 屬性和 grid-auto-rows 屬性演示地址

在講 grid-auto-columns 屬性和 grid-auto-rows 屬性以前,先來看看隱式和顯式網格的概念

隱式和顯式網格:顯式網格包含了你在 grid-template-columnsgrid-template-rows 屬性中定義的行和列。若是你在網格定義以外又放了一些東西,或者由於內容的數量而須要的更多網格軌道的時候,網格將會在隱式網格中建立行和列

假若有多餘的網格(也就是上面提到的隱式網格),那麼它的行高和列寬能夠根據 grid-auto-columns 屬性和 grid-auto-rows 屬性設置。它們的寫法和grid-template-columnsgrid-template-rows 徹底相同。若是不指定這兩個屬性,瀏覽器徹底根據單元格內容的大小,決定新增網格的列寬和行高

.wrapper {
  display: grid;
  grid-template-columns: 200px 100px;
/* 只設置了兩行,但實際的數量會超出兩行,超出的行高會以 grid-auto-rows 算 */
  grid-template-rows: 100px 100px;
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}
複製代碼

grid-template-columns 屬性和 grid-template-rows 屬性只是指定了兩行兩列,但實際有九個元素,就會產生隱式網格。經過 grid-auto-rows 能夠指定隱式網格的行高爲 50px

項目屬性介紹

grid-column-start 屬性、grid-column-end 屬性、grid-row-start 屬性以及grid-row-end 屬性

演示地址

能夠指定網格項目所在的四個邊框,分別定位在哪根網格線,從而指定項目的位置

  • grid-column-start 屬性:左邊框所在的垂直網格線
  • grid-column-end 屬性:右邊框所在的垂直網格線
  • grid-row-start 屬性:上邊框所在的水平網格線
  • grid-row-end 屬性:下邊框所在的水平網格線
.wrapper {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 20px;
  grid-auto-rows: minmax(100px, auto);
}
.one {
  grid-column-start: 1;
  grid-column-end: 2;
  background: #19CAAD;
}
.two { 
  grid-column-start: 2;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 2;
  /* 若是有重疊,就使用 z-index */
  z-index: 1;
  background: #8CC7B5;
}
.three {
  grid-column-start: 3;
  grid-column-end: 4;
  grid-row-start: 1;
  grid-row-end: 4;
  background: #D1BA74;
}
.four {
  grid-column-start: 1;
  grid-column-end: 2;
  grid-row-start: 2;
  grid-row-end: 5;
  background: #BEE7E9;
}
.five {
  grid-column-start: 2;
  grid-column-end: 2;
  grid-row-start: 2;
  grid-row-end: 5;
  background: #E6CEAC;
}
.six {
  grid-column: 3;
  grid-row: 4;
  background: #ECAD9E;
}
複製代碼

上面代碼中,類 .two 所在的網格項目,垂直網格線是從 2 到 4,水平網格線是從 1 到 2。其中它跟 .three (垂直網格線是從3 到 4,水平網格線是從 1 到 4) 是有衝突的。能夠設置 z-index 去決定它們的層級關係

grid-area 屬性

grid-area 屬性指定項目放在哪個區域,在上面介紹 grid-template-areas 的時候有提到過,這裏再也不具體展開,具體的使用能夠參考演示地址:

grid-area 以及 grid-template-areas 屬性演示地址

justify-self 屬性、align-self 屬性以及 place-self 屬性

justify-self 屬性/ align-self 屬性/ place-self 屬性演示地址

justify-self 屬性設置單元格內容的水平位置(左中右),跟 justify-items 屬性的用法徹底一致,但只做用於單個項目

align-self 屬性設置單元格內容的垂直位置(上中下),跟align-items屬性的用法徹底一致,也是隻做用於單個項目

二者很相像,這裏只拿 justify-self 屬性演示,align-self 屬性同理,只是做用於垂直方向。place-self 是設置 align-selfjustify-self 的簡寫形式,這裏也不重複介紹。

.item {
  justify-self: start | end | center | stretch;
  align-self: start | end | center | stretch;
}
複製代碼
.item {
  justify-self: start;
}
.item-1 {
  justify-self: end;
}
.item-2 {
  justify-self: center;
}
.item-3 {
  justify-self: stretch;
}
複製代碼
  • start:對齊單元格的起始邊緣

image

  • end:對齊單元格的結束邊緣

image

  • center:單元格內部居中

    image

  • stretch:拉伸,佔滿單元格的整個寬度(默認值)

    image

Grid 實戰——實現響應式佈局

通過上面的介紹,相信你們均可以看出,Grid 是很是強大的。一些常見的 CSS 佈局,如居中,兩列布局,三列布局等等是很容易實現的。咱們接下來看看 Grid 佈局是如何實現響應式佈局的

fr 實現等分響應式

fr 實現等分響應式

fr 等分單位,能夠將容器的可用空間分紅想要的多個等分空間。利用這個特性,咱們可以輕易實現一個等分響應式。grid-template-columns: 1fr 1fr 1fr 表示容器分爲三等分

.wrapper {
  margin: 50px;
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}
複製代碼

image

repeat + auto-fit——固定列寬,改變列數量

等分佈局並不僅有 Grid 佈局纔有,像 flex 佈局也能輕鬆實現,接下來看看更高級的響應式

上面例子的始終都是三列的,可是需求每每但願咱們的網格可以固定列寬,並根據容器的寬度來改變列的數量。這個時候,咱們能夠用到上面提到 repeat() 函數以及 auto-fit 關鍵字。grid-template-columns: repeat(auto-fit, 200px) 表示固定列寬爲 200px,數量是自適應的,只要容納得下,就會往上排列,代碼以及效果實現以下:

演示地址

.wrapper {
  margin: 50px;
  display: grid;
  grid-template-columns: repeat(auto-fit, 200px);
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}
複製代碼

image

repeat+auto-fit+minmax 去掉右側空白

上面看到的效果中,右側一般會留下空白,這是咱們不但願看到的。若是列的寬度也能在某個範圍內自適應就行了。minmax() 函數就幫助咱們作到了這點。將 grid-template-columns: repeat(auto-fit, 200px) 改爲 grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)) 表示列寬至少 200px,若是還有空餘則一塊兒等分。代碼以及效果以下所示:

演示地址

.wrapper {
  margin: 50px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}
複製代碼

auto-auto-minmax.gif

repeat+auto-fit+minmax-span-dense 解決空缺問題

彷佛一切進行得很順利,可是某天 UI 來講,每一個網格元素的長度可能不相同,這也簡單,經過 span 關鍵字進行設置網格項目的跨度,grid-column-start: span 3,表示這個網格項目跨度爲 3。具體的代碼與效果以下所示:

.item-3 {
  grid-column-start: span 3;
}
複製代碼

演示地址

image

不對,怎麼右側又有空白了?原來是有一些長度太長了,放不下,這個時候就到咱們的 dense 關鍵字出場了。grid-auto-flow: row dense 表示儘量填充,而不留空白,代碼以及效果以下所示:

.wrapper, .wrapper-1 {
  margin: 50px;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  grid-gap: 10px 20px;
  grid-auto-rows: 50px;
}

.wrapper-1 {
  grid-auto-flow: row dense;
}
複製代碼

image

Grid 佈局兼容性

最後,聊聊 Grid 佈局兼容性問題,在 caniuse 中,咱們能夠看到的結果以下,整體兼容性還不錯,但在 IE 10 如下不支持。我的建議在公司的內部系統運用起來是沒有問題的,但 TOC 的話,可能目前仍是不太合適

image

參考

常見的 Grid 佈局用例

CSS Grid 網格佈局教程

Grid 佈局草案

一行 CSS 代碼實現響應式佈局 – 使用 Grid 實現的響應式佈局

MDN

希望可以給你們帶來一點啓發,也歡迎你們關注個人公衆號,期待和你們一塊兒交流成長

前端雜貨鋪
相關文章
相關標籤/搜索