Grid 布局又称网格布局,是W3C提出的一个二维布局系统,它与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但它们也存在重大区别。Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。目前为止Grid布局是CSS中最为强大的布局方案。
一、基础概念与浏览器支持
截止目前为止许多浏览器都提供了对 CSS Grid 的原生支持,而且无需加浏览器前缀:Chrome(包括 Android ),Firefox,Edge,Safari(包括iOS)和 Opera 。 另一方面,Inter*** Explorer 10和11也支持Grid布局,但是是以一个过时的语法实现。
各大主流浏览器对于Grid布局的支持情况如下图所示:
PC端浏览器:
学习CSS Grid布局前,我们先需要了解以下基础概念:
1、网格容器(Grid Container)
采用Grid 网格布局的元素称为网格容器,即应用display: grid的元素。
2、网格项目(Grid Item)
网格容器内部采用Grid 网格布局的直接子元素即为网格项目,注意网格项目的子元素不再是网格项目,举个🌰:
<div id="container" style="display: grid;">
<div class="item"><span></span></div>
<div class="item"><span></span></div>
<div class="item"><span></span></div>
</div>
上面示例中container元素就是网格容器,item元素就是网格项目,注意item里的span元素并不是网格项目,不受Grid 网格布局的影响。
3、网格轨道(Grid Track)
关于网格布局可以直接想象成一个网格,而网格轨道就是这个网格中的“行”和“列”。
4、网格线(Grid Line)
划分网格的线,称为"网格线"(grid line)。水平网格线(column grid lines)划分出行,垂直网格线(row grid lines)划分出列。一个m * n的网格有m+1根水平网格线,n+1根垂直网格线。
5、单元格(Grid cell)
网格系统的最小单元,行和列的交叉区域,一个 m * n 的网格有 m * n 个单元格。
6、网格区域(Grid Area)
一个 网格区域可以由任意数量的网格单元格组成,如下图所示:
橙色边框包围内容就是一个网格区域。
二、网格容器属性
1、display属性
将元素定义为网格容器,并为其内容建立新的网格格式上下文。
属性值:
- grid: 生成块级网格
- inline-grid: 生成内联网格
- subgrid: 生成一个继承其父级网格容器的行和列的大小的网格容器,它是其父级网格容器的一个子项
注意:设为网格布局以后,容器子元素(项目)的float、display: inline-block、display: table-cell、vertical-align 和 column-* 等设置都将失效。
2、grid-template-columns,grid-template-rows属性
容器指定了网格布局以后,接着就要定义网格轨道,即划分行和列。grid-template-columns属性定义每一列的列宽,grid-template-rows属性定义每一行的行高。
用法:
grid-template-columns: <track-size> ... | <line-name> <track-size> ... ;
grid-template-rows: <track-size> ... | <line-name> <track-size> ... ;
属性值:
- track-size: 网格轨道大小,可以使用css长度,百分比或用分数(用fr单位)。
- line-name: (可选)使用方括号来指定网格线名字,方便以后的引用,网格布局允许同一根网格线有多个名字。
2.1、网格线的名称
如果没有直接指定网格线的名称网格线会自动分配正数和负数名称。示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="gbk"/>
<meta name="viewport" content="width=device-width"/>
<title>Grid 网格布局</title>
<style type="text/css"> .container { margin: 20px; display: grid; grid-template-columns: 50px 50px 50px; grid-template-rows: 50px 50px 50px;
}
.item { text-align: center; border: 1px solid gray;
} </style>
</head>
<body>
<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 class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
</div>
</body>
</html>
页面效果:
网格线名称如上图所示。
我们也可以直接给网格线定义名字,示例:
.container{display:grid;grid-template-columns: [col1-start] 50px [col1-end col2-start] 50px [col2-end col3-start] 50px [col3-end];grid-template-rows: [row1-start] 50px [row1-end row2-start] 50px [row2-end row3-start] 50px [row3-end] ;
}
其中有的网格线就不止一个名字,例如[col1-end col2-start]。
2.2、repeat()
有时候,重复写同样的值非常麻烦,尤其网格很多时。这时,可以使用repeat()函数,简化重复的值。
用法:
repeat (m , n)
参数: m: 重复的次数 n: 重复的值
上面的示例代码用repeat方法可以改写成:
.container {display: grid;grid-template-columns: repeat(3, 50px);grid-template-rows: repeat(3, 50px);
}
repeat()重复某种模式也是可以的,示例:
.container {display: grid;grid-template-columns: repeat(2, 100px 20px 80px);
}
页面效果:
2.3、auto关键字
当你设置行或列大小为auto时,浏览器为自动为网格分配空间,示例:
.container {
display: grid;grid-template-columns: 50px auto 50px;grid-template-rows: 50px auto 50px;
}
页面效果:
可以清晰地看到第二列的宽度基本上等于该列单元格的最大宽度,除非单元格内容设置了min-width且值大于最大宽度。
第二行的高度表现出了“包裹性”,即由内部文本或子元素决定高度。
2.4、auto-fill 关键字
有时,单元格的大小是固定的,但是容器的大小不确定。如果希望每一行(或每一列)容纳尽可能多的单元格,这时可以使用auto-fill关键字表示自动填充。
.container {display: grid;grid-template-columns: repeat(auto-fill, 150px);
}
页面效果:
在浏览器窗口缩放的情况下:
在浏览器窗口全屏的情况下&