Grid佈局簡介

勵步前端團隊發表於2019-05-13

Grid 佈局是網站設計的基礎,CSS Grid 是建立網格佈局最強大和最簡單的工具。

輕鬆使用 Grid 佈局提高開發效率,對複雜的網頁結構佈局更加靈活。


一、概述

Grid 將網頁劃分成一個個網格,可以任意組合不同的網格,做出各種各樣的佈局。網格是一組相交的水平線和垂直線,它定義了網格的列和行。我們可以將網格元素放置在與這些行和列相關的位置上。

Grid佈局簡介

我們比較熟悉的比如說座標軸,座標點;如果你看到上面這樣一個網格首先想到是這不就是被淘汰的表格嗎,表格之所以被淘汰最主要在效能方面,然而我們不得不承認表格對於整個網頁的佈局來說有一定的便利性。那麼現在的網格佈局就可以把表格裡面的一些較好的方便的東西抽出來,然後把效能方面較差的地方去掉,所以說網格佈局會成為將來網際網路企業的一個熱潮是有原因的。

網格佈局的優勢

固定的位置和彈性的軌道的大小
複製程式碼

你可以使用固定的軌道尺寸建立網格,比如使用畫素單位。你也可以使用比如百分比或者專門為此目的建立的新單位 fr來建立有彈性尺寸的網格。

元素位置
複製程式碼

你可以使用行號、行名或者標定一個網格區域來精確定位元素。網格同時還使用一種演算法來控制未給出明確網格位置的元素。

建立額外的軌道來包含元素
複製程式碼

可以使用網格佈局定義一個顯式網格,但是根據規範它會處理你加在網格外面的內容,當必要時它會自動增加行和列,它會盡可能多的容納所有的列。

對齊控制
複製程式碼

網格包含對齊特點,以便我們可以控制一旦放置到網格區域中的物體對齊,以及整個網格如何對齊。

控制重疊內容
複製程式碼

多個元素可以放置在網格單元格中,或者區域可以部分地彼此重疊。然後可以CSS中的z-index屬性來控制重疊區域顯示的優先順序。

Grid vs Flexbox

Grid 佈局與 Flex佈局有一定的相似性,都可以指定容器內部多個專案的位置。但是,它們也存在重大區別。Flex佈局是軸線佈局,只能指定"專案"針對軸線的位置,可以看作是一維佈局。Grid佈局則是將容器劃分成"行"和"列",產生單元格,然後指定"專案所在"的單元格,可以看作是二維佈局。Grid佈局遠比Flex佈局強大。不是說Grid佈局取代Flex佈局,實際上他倆可以很好的配合使用。

瀏覽器相容

二、重要術語

網格容器(Grid Container)

元素應用display:grid;,它是其所有網格項的父元素。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>
複製程式碼

把 container 元素變成一個 grid(網格),只要把其 display 設定為 grid。

CSS程式碼:

.container {
    display:grid;
}
複製程式碼

網格項(Grid Item)

網格容器的子元素,下面的item元素是網格項。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>
複製程式碼

網格線(Grid Line)

組成網格項的分界線。

Grid佈局簡介
記住:網格線僅僅是我們在定義網格容器的時候就產生的,跟我們的網格項沒有直接的關聯。網格線是我們在定義網格容器的時候伴隨出來的虛擬的概念,也就是說在實際的HTML中是找不到這些線的。

網格軌道(Grid Track)

兩個相鄰的網格線之間為網格軌道。

Grid佈局簡介
網格軌道的特點是一定會頂到容器的邊緣。 網格軌道必然跟網格項沒有關聯。

網格單元(Grid Cell)

兩個相鄰的列網格線和兩個相鄰的行網格線組成的是網格單元。

Grid佈局簡介

網格區域(Grid Area)

4個網格線包圍的總空間。

Grid佈局簡介

三、容器中的屬性

1、dislpay屬性

display:grid | inline-grid | subgrid;

將元素定義為grid container,併為其內容建立新的網格格式化上下文(grid formatting context)。

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
</div>
複製程式碼
.container {
    display:grid | inline-grid | subgrid;
}
複製程式碼
  • grid:生成塊級網格。
  • inline-grid:生成行內網格。
  • subgrid:如果網格容器本身是網格項(巢狀網格容器),此屬性用來繼承其父網格容器的列、行大小。
注意

當元素設定了網格佈局,column、float、clear、vertical-align屬性無效。 display:subgrid;目前所有瀏覽器都不相容。

2、grid-template屬性

1)grid-template-columns / grid-template-rows

使用以空格分隔的多個值來定義網格的列和行。

.container {
  grid-template-columns: <track-size> ... | <line-name> <track-size> ...;
  grid-template-rows: <track-size> ... | <line-name> <track-size> ...;
}
複製程式碼
注意:此屬性用在容器(container)上面。
  • 軌道大小 track-size: 可以使用css長度(px、em等)、百分比、或用分數(用 fr 單位)
  • 網格線名字 line-name:可以選擇任何名字

2)grid-template-areas

通過引用 grid-area 屬性指定的 網格區域(Grid Area) 名稱來定義網格模板。

.container {
  grid-template-areas: none|
    "grid-area-name|. grid-area-name|. grid-area-name|. ..."
    "grid-area-name|. grid-area-name|. grid-area-name|. ..."
    "......";
}
複製程式碼
  • grid-area-name:使用 grid-area 屬性設定的網格區域的名稱
  • ".":點號代表一個空網格單元
  • none:沒有定義網格區域

例如:

.container {
  grid-template-areas: 
    "head head head head"
    "main main . sidebar"
    "foot foot foot foot";
}
複製程式碼

以上例子強調以下幾點:

第一:每一行都一定要用雙引號括起來;

第二:每一個值對應一個網格單元,千萬不要上面寫了4個,下面只寫三個,這樣的話就會出問題;

第三:每個網格單元裡的區域名稱都以空格隔開;

第四:每個引號後面是沒有任何逗號或封號,僅僅是回車換行。

grid-template

在單個宣告中定義 grid-template-rows、grid-template-columns、grid-template-areas的簡寫。就個人而言,還是不要簡寫,因為簡寫之後可讀性會變差一些。

.container {
  grid-template: none | subgrid | <grid-template-rows> / <grid-template-columns>;
}
複製程式碼
  • none:將三個屬性都設定為其初始值。所謂初始值預設為一行一列一個區域,也就是說迴歸到塊元素本質,就是一個塊。網格佈局某些方面來說就是把我們的一個塊給它用一種格子的形式把他區分為多個格子,也可以理解成是多個塊。
  • subgrid:把 grid-template-rows 和 grid-template-columns 設定為subgrid,並且 grid-template-areas 設定為初始值。簡單強調一下,第一:所謂的把行跟列設定為subgrid就是說還是得自己定義一下行和列,都自己定義了,就不必再簡寫了;第二:把網格區域定義為初始值,就是每個區域的大小都是一個網格單元,如果是這樣其實就沒必要去定義它。subgrid是目前為止所有瀏覽器都不相容,那麼在這裡它依然適用,所以跟大家說一下:不推薦大家使用,只需瞭解知道即可。
  • grid-template-rows / grid-template-columns:把 grid-template-rows 和 grid-template-columns 設定為指定值,與此同時,設定 grid-template-areas 為none
.container {
  grid-template:
    [row1-start] "head head head" 25px [row1-end]
    [row2-start] "foot foot foot" 25px [row2-end]
    / auto 50px auto;
}
複製程式碼

等同於

.container {
  grid-template-rows: [row1-start] 25px [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;
  grid-template-areas: 
    "head head head" 
    "foot foot foot";
}
複製程式碼

不建議簡寫,避免混淆。

3、gap屬性

grid-column-gap / grid-row-gap

指定網格線的大小,可以想象為設定列/行之間間距的寬度。也可以說是網格軌道之間的間距

.container {
  grid-column-gap: <line-size>;
  grid-row-gap: <line-size>;
}
複製程式碼
  • line-size:一個長度值

grid-gap

grid-row-gap 和 grid-column-gap 的縮寫。

.container {
  grid-gap: <grid-row-gap> <grid-column-gap>;
}
複製程式碼
說明

起初是用 grid-gap 屬性來定義的,目前逐漸被 gap 替代。 如果沒有指定 grid-row-gap,則會被設定為與 grid-column-gap 相同的值。

4、items屬性

justify-items

沿著行軸對齊網格內的內容。

.container {
  justify-items: start | end | center | stretch;
}
複製程式碼
  • start:內容與網格區域的左端對齊
  • end:內容與網格區域的右端對齊
  • center:內容位於網格區域的中間位置
  • stretch:內容寬度佔據整個網格區域空間(這是預設值)

align-items

沿著列軸對齊網格內的內容。

.container {
  align-items: start | end | center | stretch;
}
複製程式碼
  • start:內容與網格區域的頂端對齊
  • end:內容與網格區域的底部對齊
  • center:內容位於網格區域的垂直中心位置
  • stretch:內容高度佔據整個網格區域空間(這是預設值)

place-items

設定 justify-items 和 align-items 的簡寫形式。 注意:書寫順序為先列軸屬性值後行軸屬性值。

.container {
  place-items: center;
}
複製程式碼

以上表示水平和垂直居中。

5、content屬性

justify-content

設定網格容器內的網格沿著行軸對齊網格的對齊方式。

.container {
  justify-content: start | end | center | stretch | space-around | space-between | space-evenly;    
}
複製程式碼
  • start:網格與網格容器的左邊對齊
  • end:網格與網格容器的右邊對齊
  • center:網格與網格容器的中間對齊
  • stretch:調整 grid item 的大小,讓寬度填充整個網格容器
  • space-around:在 grid item 之間設定均等寬度的空白間隙,其外邊緣間隙大小為中間空白間隙寬度的一半
  • space-between:在 grid item 之間設定均等寬度的空白間隙,其外邊緣無間隙
  • space-evenly:在每個 grid item 之間設定均等寬度的空白間隙,包括外邊緣

align-content

設定網格容器內的網格沿著列軸對齊網格的對齊方式。

.container {
  align-content: start | end | center | stretch | space-around | space-between | space-evenly;  
}
複製程式碼
  • start:網格與網格容器的頂部對齊
  • end:網格與網格容器的底部對齊
  • center:網格與網格容器的中間對齊
  • stretch:調整 grid item 的大小,讓高度填充整個網格容器
  • space-around:在 grid item 之間設定均等高度的空白間隙,其外邊緣間隙大小為中間空白間隙寬度的一半
  • space-between:在 grid item 之間設定均等高度的空白間隙,其外邊緣無間隙
  • space-evenly:在每個 grid item 之間設定均等高度的空白間隙,包括外邊緣

place-content

設定 align-content 和 justify-content 的簡寫形式。 注意:書寫順序為先列軸對齊屬性值後行軸對齊屬性值。

6、grid-auto屬性

grid-auto-columns / grid-auto-rows

指定自動生成的網格軌道(又名隱式網格軌道)的大小。

隱式網格軌道

隱式網格軌道在顯示的定位超出指定網格範圍的行或列時被建立。也就是說網格項超出,一種是太多了,還有一種分兩種情況:如果說僅僅因為太多的話,我們只需要控制行就可以了,列這一塊的話肯定是跟著上面是一樣的。但是有時列也會超出,超出情況會在講到網格項的地方提到過,當網格項確定在網格單元或網格區域的時候是可以控制的,控制的時候除了網格區域的名字之外,它也可以通過地址條網格線來控制,但是這個線的名字如果是超過的時候就會出來,那麼在這種情況下就會自動生成隱式網格軌道。

隱式網格軌道個人是不建議大家使用的,因為我們的這個隱式網格我們在容器當中一般來說我們在容器中統攬大局然後摳出區域性,結果區域性不由大局控制反而影響大局,這就有點反客為主,喧賓奪主的意思了,那在控制起來勢必會有混亂,所以隱式網格軌道不是特別提倡大家使用。

.container {
  grid-auto-columns: <track-size> ...;
  grid-auto-rows: <track-size> ...;
}
複製程式碼
  • track-size:可以是一個長度值,一個百分比,或者一個自由空間的一部分(使用 fr 單位)

grid-auto-flow

控制自動佈局演算法的工作方式。

.container {
  grid-auto-flow: row | column | row dense | column dense
}
複製程式碼
  • row:告訴自動佈局演算法依次填充每行,根據需要新增新行 (預設)
  • column:告訴自動佈局演算法依次填充每列,根據需要新增新列
  • dense:告訴自動佈局演算法,如果後面出現較小的 grid item,則嘗試在網格中填充空洞
注意:dense 只會更改網格項的可視順序,並可能導致它們出現亂序,這對可訪問性不利。

7、grid屬性

在單個屬性中設定所有以下屬性的簡寫: grid-template-rows, grid-template-columns, grid-template-areas, grid-auto-rows, grid-auto-columns, 和 grid-auto-flow 。

當然像左對齊、右對齊這些對齊方式等就不能簡寫在上面。就是說我們可以把多少行多少列以及它的區域還有隱式軌道以及他的佈局方式都可以簡寫到 grid 裡面並且同時將 sets grid-column-gap 和 grid-row-gap設定為他們的初始值,即使它們不能被此屬性顯示設定。

.container {
  grid: none | <grid-template-rows> / <grid-template-columns> | <grid-auto-flow> [<grid-auto-rows> [/ <grid-auto-columns>]];
}
複製程式碼
  • none:將所有子屬性設定為其初始值。
  • grid-template-rows / grid-template-columns:將 grid-template-rows 和 grid-template-columns 分別設定為指定值,將所有其他子屬性設定為其初始值
  • grid-auto-flow [grid-auto-rows [/ grid-auto-columns]]:接受所有與 grid-auto-flow,grid-auto-rows 和 grid-auto-columns 相同的值。如果省略 grid-auto-columns,則將其設定為 grid-auto-rows指定的值。如果兩者都被省略,則它們被設定為它們的初始值
.container {
  grid: [row1-start] "head head head" 1fr [row1-end]
        [row2-start] "foot foot foot" 25px [row2-end]
        / auto 50px auto;
}
複製程式碼

等價於:

.container {
  grid-template-areas: 
    "head head head"
    "foot foot foot";
  grid-template-rows: [row1-start] 1fr [row1-end row2-start] 25px [row2-end];
  grid-template-columns: auto 50px auto;    
}
複製程式碼

簡寫形式就簡單的做一個介紹,實際開發當中不建議簡寫形式。

四、CSS函式

  • repeat()
  • fit-content()
  • minmax()

1、repeat()

重複

跟蹤列表的重複片段,允許大量顯示重複模式的列或行以更緊湊的形式編寫。

.container {
  grid-template-columns: repeat(repeat, values);
  grid-template-rows: repeat(repeat, values);
}
複製程式碼
可用範圍:這個函式可以用在 CSS Grid 屬性 grid-template-columns 和 grid-template-rows。

重複次數

  • number:整數,確定確切的重複次數。
  • auto-fill:以網格項為準自動填充。
  • auto-fit:以網格容器為準自動填充。

  • length:非負長度。
  • percentage:相對於列軌道中網格容器的內聯大小的非負百分比,以及行軌道中網格容器的塊長度。
  • flex:單位為 fr 的非負維度,指定軌道彈性佈局的係數值。
  • max-content:表示網格的軌道長度自適應內容最大的那個單元格。
  • min-content:表示網格的軌道長度自適應內容最小的那個單元格。
  • auto:作為最大值時,等價於 max-content。作為最小值時,它表示軌道中單元格最小長寬(由min-width/min-height)的最大值。

2、fit-content()

內容適配

根據公式min(最大大小、最大值(最小大小、引數))將給定大小夾緊為可用大小。

.container {
  grid-template-columns: fit-content([ <length> | <percentage> ]);
  grid-template-rows: fit-content([ <length> | <percentage> ]);
}
複製程式碼

  • length:一個絕對的長度。
  • percentage:相對於給定軸上可用空間的百分比。

3、minmax()

長寬範圍

定義了一個長寬範圍的閉區間。

minmax([ <length> | <percentage> | <flex> | min-content | max-content | auto ],
[ <length> | <percentage> | <flex> | min-content | max-content | auto ]);
複製程式碼

值(跟repeat的取值是一樣的)

  • length:非負長度。
  • percentage:相對於列軌道中網格容器的內聯大小的非負百分比,以及行軌道中網格容器的塊長度。
  • flex:單位為 fr 的非負維度,指定軌道彈性佈局的係數值。
  • max-content:表示網格的軌道長度自適應內容最大的那個單元格。
  • min-content:表示網格的軌道長度自適應內容最小的那個單元格。
  • auto:作為最大值時,等價於 max-content。作為最小值時,它表示軌道中單元格最小長寬(由min-width/min-height)的最大值。

例如:

.container {
  grid-template-columns: minmax(300px, 50px);
}
複製程式碼

minmax()這個函式前面‘300px’是最小值,後面‘50px’是最大值,也就是說範圍是從小到大的。當最小值大於最大值時,最大值將被忽略,整列會成為最小值。

五、網格項上的屬性

  • start / end :規定每一個網格項在那個區域當中

  • grid-area:跟網格區域一樣

  • self:自身裡面的對齊方式

start / end 和 grid-area 兩個屬性都是規劃出一個網格區域,把網格項放在一個網格區域裡面,唯一不同的是 start / end 是通過網格線來規劃出網格區域,而 grid-area 是通過網格區域在並列網格容器當中時就定義好的網格區域,然後直接來讀取這個網格區域就可以了。

1、start / end 屬性

grid-column-start / grid-column-end / grid-row-start / grid-row-end

使用特定網格線來確定 網格項(grid item)在網格內的位置。

.item {
  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
}
複製程式碼
屬性值
  • line :可以是一個數字來指代相應編號的網格線,也可使用名稱指代相應命名的網格線
  • span number :網格項將跨越指定數量的網格軌道
  • span name :網格項將跨越一些軌道,直到碰到指定命名的網格線
  • auto:自動佈局,或者自動跨度,或者跨越一個預設的軌道
說明
  • 如果沒有宣告 grid-column-end / grid-row-end,預設情況下,該網格項將跨越1個軌道。

  • 網格項可以相互重疊。可以使用 z-index 來控制它們的堆疊順序。

grid-column / grid-row

grid-column-start + grid-column-end 和 grid-row-start + grid-row-end 的簡寫形式。

.item {
  grid-column: <start-line> / <end-line> | <start-line> / span <value>;
  grid-row: <start-line> / <end-line> | <start-line> / span <value>;
}
複製程式碼

個人建議:斜槓前後的空格千萬不要省略,有時可以識別,有時不可識別,對於瀏覽器來說小版本的話就會有差別。建議斜槓前後都要有空格。

屬性值

start-line / end-line:每個值的用法都和屬性分開寫時的用法一樣

例如:

CSS程式碼如下:

.container > .item:nth-child(1) {
    grid-column-start: 2;
    grid-column-end: 4;
    grid-row-start: 2;
    grid-row-end: 4;
}
複製程式碼

等同於

.container > .item:nth-child(1) {
    grid-column: 2 / 4;
    grid-row: 2 / 4;
}
複製程式碼

等同於

.container > .item:nth-child(1) {
    grid-column: 2 / span 2;
    grid-row: 2 / span 2;
}
複製程式碼

2、grid-area 屬性

網格區域

給 gird item 進行命名以便於使用 grid-template-areas 屬性建立模板時來進行引用。

.item {
  grid-area: <name> | <row-start> / <column-start> / <row-end> / <column-end>;
}
複製程式碼
屬性值
  • name :grid-template-areas 中定義的命名
  • row-start / column-start / row-end / column-end:可以是數字,也可以是網格線的名字
例如:

CSS程式碼如下:

.container > .item-a {
    grid-area: row1-start / 2 / 3 / five;
}
複製程式碼

等同於

.container > .item-a {
    grid-column-start: 2;
    grid-column-end: five;
    grid-row-start: row1-start;
    grid-row-end: 3;
}
複製程式碼

Grid佈局簡介

例如:

CSS程式碼如下:

.container > .item-a {
    grid-column: 2 / span 2;
    grid-row: 2 / span 2;
}
複製程式碼

等同於

.container > .item-a {
    grid-area: 2 / 2 / 4 / 4;
}
複製程式碼

3、self 屬性

justify-self

沿著行軸對齊 grid-item 裡的內容。

.item {
  justify-self: start | end | center | stretch;
}
複製程式碼
屬性值
  • start:將內容對齊到網格區域的左端
  • end:將內容對齊到網格區域的右端
  • center:將內容對齊到網格區域的中間
  • stretch:填充網格區域的寬度(這是預設值)

align-self

沿著列軸對齊 grid-item 裡的內容。

.item {
  align-self: start | end | center | stretch;
}
複製程式碼
屬性值
  • start:將內容對齊到網格區域的頂部
  • end:將內容對齊到網格區域的底部
  • center:將內容對齊到網格區域的中間
  • stretch:填充網格區域的高度(這是預設值)

本篇文章到此結束,歡迎提建議哈!

參考文獻:

developer.mozilla.org/zh-CN/docs/…

www.html.cn/archives/85…

相關文章