網格布局(Grid Layout)也叫柵格布局,與表格布局類似,也依賴行和列。但與之不同的是,網格布局能直接控制HTML文檔中元素的順序、位置和大小等,而不用再借助輔助元素。
## 一、術語
  下圖展示了CSS規范中定義的網格。
:-: 
  (1)網格容器(grid container)由display屬性的兩個特殊值(grid和inline-grid)所創建,由于它不是塊級容器,因此其布局不受浮動和外邊距塌陷的影響。
  (2)網格項(grid item)也叫網格元素,是網格容器的子元素,注意,它的后代元素不是網格項,但它自身也能變為網格容器。
  (3)網格線(grid line)為網格容器劃分不同的區域,注意,網格線的數量沒有限制。
  (4)網格單元(grid cell)是由四條網格線限定的區域,其內部不會有其它的網格線。
  (5)網格區域(grid area)由一個或多個相鄰的網格單元組成的矩形區域,最大的網格區域會包含所有的網格單元。
  (6)網格軌道(grid track)是由兩條網格線夾住的區域,從容器的一邊延伸到另一邊,水平方向的叫網格行(grid row),垂直方向的叫網格列(grid column),它們的尺寸由網格線的位置決定。
## 二、行和列
  grid-template-rows和grid-template-columns兩個屬性可以定義網格線的名稱和網格軌道的尺寸,前者可聲明行的數量,后者可聲明列的數量。
  在下面的示例中,將網格容器分成兩行三列,其中第一列的寬度是50px(即第二條網格線在距離容器左邊界50px的位置),第二列的寬度是容器寬度的一半(即第三條網格線距離上一條網格線的偏移是容器寬度的一半),第三列的寬度是30px。
~~~html
<style>
div {
display: grid;
width: 200px;
height: 100px;
grid-template-rows: 50px 50px;
grid-template-columns: 50px 50% 30px;
}
</style>
<div>
<section>1</section>
<section>2</section>
<section>3</section>
<section>4</section>
<section>5</section>
<section>6</section>
</div>
~~~
  下圖的左側是上述代碼的效果,右側中的虛線是生成的網格線,后文會反復使用這種格式的標注圖。注意,網格線可以不與容器的邊界接觸,兩個屬性中的百分數參照的是網格容器的寬度或高度。
:-: 
  如果要占滿網格容器的橫向空間,那么可以使用minmax()函數,如下所示。minmax(30px, 100%)表示該列所占的空間在30px和容器寬度之間,即不能小于30px并且不能大于容器寬度,效果如下圖所示。
~~~css
div {
grid-template-columns: 50px 50% minmax(30px, 100%);
}
~~~
:-: 
  如果要為網格線命名,那么可以將名稱放在值的恰當位置(例如名稱在值之前,樣式如下),并用方括號包裹。
~~~css
div {
grid-template-columns: [col-a] 50px [col-b] 50% [col-c] minmax(30px, 100%) [col-d];
}
~~~
**1)fr**
  在網格布局中,包含一個全新的fr單位,能將空間分成一定份數,彈性的分配給行或列,這個單位的作用類似于彈性盒中的flex-grow屬性。在下面的示例中,將容器均分為3列,效果如下圖所示。
~~~css
div {
grid-template-columns: 1fr 1fr 1fr;
}
~~~
:-: 
  注意,fr可與其它長度單位混合使用,其作用的是可用空間,即剩余空間。在下面的示例中,將第一列寬度固定,剩余的空間由兩列均分,效果如下圖所示。
~~~css
div {
grid-template-columns: 30px 1fr 1fr;
}
~~~
:-: 
**2)min-content和max-content**
  當網格軌道的尺寸與其內容有關時,可使用這兩個關鍵字。min-content會占據內容所需的最小空間,例如將min-content應用于網格容器的第二列,樣式如下,效果如下圖所示,網格項中有大量的斷行。
~~~html
<style>
div {
grid-template-columns: 30px min-content 1fr;
}
</style>
<div>
<section>1</section>
<section>2 2 2</section>
<section>3</section>
<section>4</section>
<section>5</section>
<section>6</section>
</div>
~~~
:-: 
  max-content的作用正好與min-content相反,它會占據內容所需的最大空間。將max-content也應用到上面的第二列,樣式如下,效果如下圖所示,網格項為了防止文本換行,會不斷地擴大其寬度。
~~~css
div {
grid-template-columns: 30px max-content 1fr;
}
~~~
:-: 
**3)fit-content()**
  該函數的參數是一個長度值或百分數,能將占用空間指定成特定的值,它相當于下面等號右邊的公式。
~~~
fit-content(argument) = min(max-content, max(min-content, argument))
~~~
  先將接收的參數與min-content比較,得出較大值,再將該值與max-content比較,得到較小值。理解起來比較拗口,如果換成minmax()函數,含義就比較清晰了,與fit-content(argument)等價的公式如下。
~~~
minmax(min-content, max-content)
~~~
**4)repeat()**
  該函數能為網格軌道聲明重復的行或列,它的第一個參數是重復次數,第二個參數是軌道尺寸,例如將網格容器均分成三列,樣式如下。
~~~css
div {
grid-template-columns: repeat(3, 1fr);
/* 等價于 */
grid-template-columns: repeat(1fr, 1fr, 1fr);
}
~~~
  注意,軌道尺寸不局限于一個,可以指定多個,樣式如下,效果如下圖所示。
~~~css
div {
grid-template-columns: repeat(2, 20px 1fr);
}
~~~
:-: 
## 三、網格項
  通過起始和終止處的網格線的名稱或編號可指定網格項的位置,其中列的編號從左到右依次遞增,行的編號從上到下依次遞增,如下圖所示。
:-: 
  在下面的示例中,將網格容器均分成三行四列,并且把第一個section元素指定到第二行第二列的位置,效果如下圖所示。
~~~html
<style>
div {
grid-template-rows: repeat(3, 1fr);
grid-template-columns: repeat(4, 1fr);
}
.one {
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 2;
grid-column-end: 3;
}
</style>
<div>
<section class="one">1</section>
<section>2</section>
<section>3</section>
<section>4</section>
<section>5</section>
<section>6</section>
<section>7</section>
<section>8</section>
<section>9</section>
<section>10</section>
</div>
~~~
:-: 
  將下面的樣式添加給第一個section元素,可以得到跨列的效果,如下圖所示。
~~~css
.two {
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 2;
grid-column-end: 4;
}
~~~
:-: 
  網格線的編號支持負數,也就是以相反的方式計數,從后往前或從下往上,例如將第一個section元素放置在容器的右下角,樣式如下,效果如下圖所示。
~~~css
.three {
grid-row-start: -2;
grid-row-end: -1;
grid-column-start: -2;
grid-column-end: -1;
}
~~~
:-: 
**1)span**
  還有另一種方式可用來指定網格項的位置,即用span和正整數組合,表示要跨的網格軌道數目。在下面的樣式中,“span 2”用于跨過兩列。
~~~css
.four {
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: 2;
grid-column-end: span 2;
}
~~~
  當把span應用于grid-row-start或grid-column-start屬性時,將會沿著網格開始的方向計數,樣式如下,效果如下圖所示。
~~~css
.five {
grid-row-start: 2;
grid-row-end: 3;
grid-column-start: span 2;
grid-column-end: 3;
}
~~~
:-: 
  注意,span后面可以省略數字,默認是1,但不能跟零或負數。
**2)簡寫屬性**
  grid-row是grid-row-start和grid-row-end的簡寫屬性,grid-column是grid-column-start和grid-column-end的簡寫屬性。
  grid-row和grid-column可分別將行和列的起止網格線聲明在一行,并用斜杠(/)分隔,如下所示。
~~~css
.six {
grid-row: 2 / 3;
grid-column: 2 / span 2;
}
~~~
  注意,由于默認跨度是1,因此可以省略grid-row和grid-column斜杠后的數字,如下所示。
~~~css
.seven {
grid-row: 2;
grid-column: 2;
}
~~~
  grid-area是grid-row-start、grid-row-end、grid-column-start和grid-column-end的簡寫屬性,也可用斜杠(/)將值分隔,如下所示。
~~~css
.eight {
grid-area: 2 / 2 / 3 / span 2;
}
~~~
  注意,網格線值的順序是:起始行、起始列、終止行、終止列,圍繞網格項逆時針排列。
**3)重疊**
  當兩個網格項發生重疊時,可通過z-index屬性來決定誰在上,誰在下。例如為兩個section元素分別添加下面的樣式,效果如下圖所示,第二個section元素覆蓋了第一個section元素。
~~~html
<style>
.overlap1 {
grid-row: 1;
grid-column: 1 / span 2;
}
.overlap2 {
grid-row: 1;
grid-column: 2 / span 2;
}
</style>
<div>
<section class="overlap1">1</section>
<section class="overlap2">2</section>
<section>3</section>
<section>4</section>
<section>5</section>
<section>6</section>
<section>7</section>
<section>8</section>
<section>9</section>
<section>10</section>
</div>
~~~
:-: 
  當為第一個section元素添加z-index屬性后(樣式如下),就會覆蓋第二個section元素,效果如下圖所示。
~~~css
.overlap1 {
z-index: 1;
}
~~~
:-: 
**4)自動增加網格線**
  當網格項超出容器邊界時,可通過grid-auto-rows和grid-auto-columns分別控制行和列的尺寸。
  在下面的示例中,將網格容器分成兩行三列,它的第七個超出邊界的網格項的高度默認是內容的高度,即“height:auto”,效果如下圖所示。
~~~html
<style>
div {
grid-template-rows: 50px 50px;
grid-template-columns: repeat(3, 1fr);
}
</style>
<div>
<section>1</section>
<section>2</section>
<section>3</section>
<section>4</section>
<section>5</section>
<section>6</section>
<section>7</section>
</div>
~~~
:-: 
  當為網格容器添加grid-auto-rows屬性后,就能改變網格項的高度,如下所示,效果如下圖所示。
~~~css
div {
grid-auto-rows: 50px;
}
~~~
:-: 
  grid-auto-columns的用法與之類似,但修改的是超出邊界的網格項的寬度。在下圖中,左側是默認超出時的寬度,即內容的寬度(width:auto);右側是為容器添加下面樣式后的寬度。
~~~css
div {
grid-auto-flow: column;
grid-auto-columns: 50px;
}
~~~
:-: 
  注意,grid-auto-flow是一個網格流屬性,可讓網格項按列排序,后文第五節會重點講解。
## 四、網格區域
  通過grid-template-areas屬性能夠以可視化的方式聲明網格布局,其值是用空格或換行符分隔的字符串列表,每段字符串又是以空格分隔的自定義標識符,如下所示。
~~~css
div {
grid-template-areas: "a b b"
"a . c";
}
~~~
  每個標識符表示一個網格單元,注意,組合在一起的形狀必須得是矩形。當只需要占位時,可以使用點號(.)創建匿名單元。
  為了將網格項與網格區域關聯,需要使用grid-area屬性。通過它來引用命名好的網格區域,如下所示,grid-area的屬性值就是grid-template-areas屬性中的標識符,效果如下圖所示。
~~~html
<style>
.a {
grid-area: a;
}
.b {
grid-area: b;
}
.c {
grid-area: c;
}
</style>
<div>
<section class="a">a</section>
<section class="b">b</section>
<section class="c">c</section>
</div>
~~~
:-: 
## 五、網格流
  網格流可由grid-auto-flow屬性控制,它分為兩種填充方式:逐行和逐列,并且兩者都可通過稠密模式更高效地占用網格單元。
  在下面的示例中,第一個div元素中的網格項會先填滿一行再換到下一行,效果如下圖的左側;第二個div元素中的網格項會先填滿一列再換到下一列,效果如下圖的右側。
~~~html
<style>
.row {
grid-auto-flow: row;
}
.column {
grid-auto-flow: column;
}
</style>
<div class="row">
<section>1</section>
<section>2</section>
<section>3</section>
<section>4</section>
<section>5</section>
<section>6</section>
</div>
<div class="column">
<section>1</section>
<section>2</section>
<section>3</section>
<section>4</section>
<section>5</section>
<section>6</section>
</div>
~~~
:-: 
  grid-auto-flow屬性默認是稀疏模式,而稠密模式會盡力找出最前面的空位置。假設網格容器包含三個網格項,其中有兩個會占用兩個網格單元,樣式如下,效果如下圖所示,第一個網格項之后的網格單元閑置著。
~~~html
<style>
.across {
grid-column: auto / span 2;
}
</style>
<div class="row">
<section class="across">1</section>
<section class="across">2</section>
<section>3</section>
</div>
~~~
:-: 
  當為網格容器的grid-auto-flow屬性添加dense后,就能觸發稠密模式,得到的效果如下圖所示,第三個網格項會移動到第一個之后。
~~~css
.row {
grid-auto-flow: row dense;
}
~~~
:-: 
## 六、間距
  間距(gutter)也叫空距或欄距,用于控制兩個網格軌道之間的距離,類似于將網格線加粗,使其具有寬度。
  間距可由grid-row-gap和grid-column-gap兩個屬性設定,但要注意,現在這兩個屬性已改名成row-gap和column-gap,它們相當于表格樣式中的border-spacing屬性。在下面的示例中,為網格容器添加了兩個方向的間距,效果如下圖所示。
~~~css
div {
row-gap: 10px;
column-gap: 20px;
}
~~~
:-: 
  grid-gap是一個簡寫屬性,可將行和列的間距組合在一起定義,下面樣式的效果與上圖一樣。注意,該屬性現已改名成gap。
~~~css
div {
gap: 10px 20px;
}
~~~
  順便說一句,CSS規范提供了一個簡寫屬性:grid,可將上述grid-template-rows、grid-auto-rows、row-gap等屬性組合在一起聲明。
## 七、對齊方式
  網格布局中的對齊屬性與彈性盒中的類似,也是使用下表中的相關屬性。
:-: 
**1)對齊網格項**
  justify-self和align-self兩個屬性適用于單個網格項,它們的默認值都是stretch,其它可選的關鍵字包括start、end和center等。
  假設有一個兩行三列的網格容器,為它的四個網格項分別添加四個不同關鍵字的justify-self屬性,效果如下圖所示。
~~~html
<style>
div {
display: grid;
grid-template-rows: repeat(2, 1fr);
grid-template-columns: repeat(3, 1fr);
}
.justify-self-start {
justify-self: start;
}
.justify-self-end {
justify-self: end;
}
.justify-self-center {
justify-self: center;
}
.justify-self-stretch {
justify-self: stretch;
}
</style>
<div>
<section class="justify-self-start">start</section>
<section class="justify-self-center">center</section>
<section class="justify-self-end">end</section>
<section class="justify-self-stretch">stretch</section>
</div>
~~~
:-: 
  將這四個關鍵字賦給align-self屬性,再應用到另一個兩行三列的網格容器中,得到的效果如下圖所示。
:-: 
  justify-items和align-items兩個屬性適用于網格容器,它們的默認值也是stretch,可選的關鍵字與之前的兩個屬性類似,下面的樣式在為之前的div元素(網格容器)添加justify-items屬性。
~~~css
div {
justify-items: start;
}
~~~
**2)對齊網格軌道**
  justify-content和align-content兩個屬性適用于網格容器,可用的關鍵字包括start、end、center、space-between和space-around等。
  下圖展示了這五個關鍵字賦給justify-content屬性后,再分別應用于網格容器的效果。
:-: 
  下圖展示了這五個關鍵字賦給align-content屬性后,再分別應用于網格容器的效果。
:-: 
## 八、排序
  在網格布局中,也可以像彈性盒那樣使用order屬性調整網格項的順序。注意,order屬性作用于網格項,其值是一個整數,包括零和負數。在下面的示例中,將第一個和第三個section元素調換了次序,效果如下圖所示。
~~~html
<style>
.first {
order: 1;
}
.second {
order: 2;
}
.third {
order: 3;
}
</style>
<div>
<section class="third">1</section>
<section class="second">2</section>
<section class="first">3</section>
</div>
~~~
:-: 
*****
> 原文出處:
[博客園-CSS躬行記](https://www.cnblogs.com/strick/category/1667864.html)
[知乎專欄-CSS躬行記](https://zhuanlan.zhihu.com/pwcss)
已建立一個微信前端交流群,如要進群,請先加微信號freedom20180706或掃描下面的二維碼,請求中需注明“看云加群”,在通過請求后就會把你拉進來。還搜集整理了一套[面試資料](https://github.com/pwstrick/daily),歡迎瀏覽。

推薦一款前端監控腳本:[shin-monitor](https://github.com/pwstrick/shin-monitor),不僅能監控前端的錯誤、通信、打印等行為,還能計算各類性能參數,包括 FMP、LCP、FP 等。
- ES6
- 1、let和const
- 2、擴展運算符和剩余參數
- 3、解構
- 4、模板字面量
- 5、對象字面量的擴展
- 6、Symbol
- 7、代碼模塊化
- 8、數字
- 9、字符串
- 10、正則表達式
- 11、對象
- 12、數組
- 13、類型化數組
- 14、函數
- 15、箭頭函數和尾調用優化
- 16、Set
- 17、Map
- 18、迭代器
- 19、生成器
- 20、類
- 21、類的繼承
- 22、Promise
- 23、Promise的靜態方法和應用
- 24、代理和反射
- HTML
- 1、SVG
- 2、WebRTC基礎實踐
- 3、WebRTC視頻通話
- 4、Web音視頻基礎
- CSS進階
- 1、CSS基礎拾遺
- 2、偽類和偽元素
- 3、CSS屬性拾遺
- 4、浮動形狀
- 5、漸變
- 6、濾鏡
- 7、合成
- 8、裁剪和遮罩
- 9、網格布局
- 10、CSS方法論
- 11、管理后臺響應式改造
- React
- 1、函數式編程
- 2、JSX
- 3、組件
- 4、生命周期
- 5、React和DOM
- 6、事件
- 7、表單
- 8、樣式
- 9、組件通信
- 10、高階組件
- 11、Redux基礎
- 12、Redux中間件
- 13、React Router
- 14、測試框架
- 15、React Hooks
- 16、React源碼分析
- 利器
- 1、npm
- 2、Babel
- 3、webpack基礎
- 4、webpack進階
- 5、Git
- 6、Fiddler
- 7、自制腳手架
- 8、VSCode插件研發
- 9、WebView中的頁面調試方法
- Vue.js
- 1、數據綁定
- 2、指令
- 3、樣式和表單
- 4、組件
- 5、組件通信
- 6、內容分發
- 7、渲染函數和JSX
- 8、Vue Router
- 9、Vuex
- TypeScript
- 1、數據類型
- 2、接口
- 3、類
- 4、泛型
- 5、類型兼容性
- 6、高級類型
- 7、命名空間
- 8、裝飾器
- Node.js
- 1、Buffer、流和EventEmitter
- 2、文件系統和網絡
- 3、命令行工具
- 4、自建前端監控系統
- 5、定時任務的調試
- 6、自制短鏈系統
- 7、定時任務的進化史
- 8、通用接口
- 9、微前端實踐
- 10、接口日志查詢
- 11、E2E測試
- 12、BFF
- 13、MySQL歸檔
- 14、壓力測試
- 15、活動規則引擎
- 16、活動配置化
- 17、UmiJS版本升級
- 18、半吊子的可視化搭建系統
- 19、KOA源碼分析(上)
- 20、KOA源碼分析(下)
- 21、花10分鐘入門Node.js
- 22、Node環境升級日志
- 23、Worker threads
- 24、低代碼
- 25、Web自動化測試
- 26、接口攔截和頁面回放實驗
- 27、接口管理
- 28、Cypress自動化測試實踐
- 29、基于Electron的開播助手
- Node.js精進
- 1、模塊化
- 2、異步編程
- 3、流
- 4、事件觸發器
- 5、HTTP
- 6、文件
- 7、日志
- 8、錯誤處理
- 9、性能監控(上)
- 10、性能監控(下)
- 11、Socket.IO
- 12、ElasticSearch
- 監控系統
- 1、SDK
- 2、存儲和分析
- 3、性能監控
- 4、內存泄漏
- 5、小程序
- 6、較長的白屏時間
- 7、頁面奔潰
- 8、shin-monitor源碼分析
- 前端性能精進
- 1、優化方法論之測量
- 2、優化方法論之分析
- 3、瀏覽器之圖像
- 4、瀏覽器之呈現
- 5、瀏覽器之JavaScript
- 6、網絡
- 7、構建
- 前端體驗優化
- 1、概述
- 2、基建
- 3、后端
- 4、數據
- 5、后臺
- Web優化
- 1、CSS優化
- 2、JavaScript優化
- 3、圖像和網絡
- 4、用戶體驗和工具
- 5、網站優化
- 6、優化閉環實踐
- 數據結構與算法
- 1、鏈表
- 2、棧、隊列、散列表和位運算
- 3、二叉樹
- 4、二分查找
- 5、回溯算法
- 6、貪心算法
- 7、分治算法
- 8、動態規劃
- 程序員之路
- 大學
- 2011年
- 2012年
- 2013年
- 2014年
- 項目反思
- 前端基礎學習分享
- 2015年
- 再一次項目反思
- 然并卵
- PC網站CSS分享
- 2016年
- 制造自己的榫卯
- PrimusUI
- 2017年
- 工匠精神
- 2018年
- 2019年
- 前端學習之路分享
- 2020年
- 2021年
- 2022年
- 2023年
- 2024年
- 日志
- 2020