CSS Grid网格布局
Grid 布局与 Flex 布局有一定的相似性,都可以指定容器内部多个项目的位置。但是,它们也存在重大区别。同时跟表格 <table>
也有些相似,也有 单元格
的概念。
Flex 布局是轴线布局,只能指定 “项目” 针对轴线的位置,可以看作是一维布局。Grid 布局则是将容器划分成 “行” 和 “列”,产生单元格,然后指定 “项目所在” 的单元格,可以看作是二维布局。Grid 布局是继 Flex 布局之后的又一布局利器。
基本概念
容器和项目
采用网格布局的区域,称为 “容器”(container)。容器内部采用网格定位的子元素,称为 “项目”(item)。
1 | <div class="container"> |
上面代码中,最外层的 <div>
元素就是 容器
,内层的 6 个 <div>
元素就是 项目
。
注意:项目只能是容器的顶层子元素,不包含项目的子元素,比如上面代码的
<span>
元素 和文本内容就不是项目。Grid 布局只对项目生效。
行和列
容器里面的 水平区域
称为 “行”(row),垂直区域
称为 “列”(column)。
上图中,水平的深色区域就是 “行”,垂直的深色区域就是 “列”。
单元格
行和列的交叉区域,称为 “单元格”(cell)。
正常情况下,n行 和 m列
会产生 n x m
个单元格。比如,3行3列
会产生 9
个单元格。
网格线
划分网格的线,称为 “网格线”(grid line)。水平网格线划分出行,垂直网格线划分出列。
正常情况下,n
行有 n + 1
根水平网格线,m
列有 m + 1
根垂直网格线,比如三行就有四根水平网格线。
上图是一个 4 x 4 的网格,共有 5 根水平网格线和 5 根垂直网格线。
容器规则
Grid 布局的规则分成两类。一类定义在容器上面,称为 容器规则
;另一类定义在项目上面,称为项目规则
。这部分先介绍 容器规则
。
display
将容器元素的 display
规则设置为 grid
即可启用 网格布局。
1 | .grid { |
默认情况下,容器元素都是块级元素,但也可以设成行内元素。
1 | .grid { |
注意,设为网格布局以后,容器的float、display: inline-block、display: table-cell、vertical-align和column-*等设置都将失效。
grid-template-rows
grid-template-columns
容器指定了网格布局以后,接着就要划分行和列。grid-template-columns
规则定义每一列的列宽,grid-template-rows
规则定义每一行的行高。
1 | .box-1 { |
如上图,使用的是绝对单位,定义了 3*3
的网格布局,列宽和行高 还可以使用百分比,如下:
1 | .box-2 { |
使用百分比单位时,会根据容器的宽高按比例自动分配行高和列宽。
网格线的名称
grid-template-columns
和 grid-template-rows
的值中可以设置每条网格线的名称。
下面代码指定网格布局为 2行 x 3列
,因此有 4
根垂直网格线和 3
根水平网格线。方括号里面依次是这 7
根线的名字。
网格布局允许同一根线有多个名字,比如 [fifth-line row-5]
。
1 | <div class="grid box-3"> |
1 | .box-3 { |
grid-row-gap
grid-column-gap
grid-row-gap
定义网格中行与行之间的间距。grid-column-gap
定义网格中列与列之间的间距。
1 | <div class="grid box-4"> |
1 | .box-4 { |
如上图,定义了 2*3
的网格,行与行之间的间隔为 50px
,列与列之间的间隔为 50px
。
grid-gap
grid-gap
是 grid-row-gap
和 grid-column-gap
的简写属性。
1 | grid-gap: [grid-row-gap] [grid-column-gap]; |
如果 grid-gap
省略了第二个值,浏览器认为第二个值等于第一个值。
根据最新标准,上面三个属性名的
grid-
前缀已经删除,grid-column-gap
和grid-row-gap
写成column-gap
和row-gap
,grid-gap
写成gap
。
grid-template-areas
网格布局允许指定 “区域”(area),一个区域由单个或多个单元格组成。grid-template-areas
属性用于定义区域。
下面代码先划分出 6 个单元格,然后将其定名为 a 到 f 的 6 个区域,分别对应这 6 个单元格。 如果某些区域不需要利用,则使用 “点”(.)表示。
1 | <div class="grid box-5"> |
1 | .box-5 { |
grid-auto-flow
划分网格以后,容器中的子元素 (项目) 会按照顺序,自动放置在每一个网格。
默认的放置顺序是 “先行后列”,即先填满第一行,再开始放入第二行,以此类推。
1 | grid-auto-flow: row; |
将 grid-auto-flow
的值设置为 column
后,变为 “先列后行”。
1 | grid-auto-flow: column; |
grid-auto-flow
的值还可以设成 row dense
和 column dense
。这两个值主要用于,某些项目指定位置以后,剩下的项目怎么自动放置。
让 1号项目 和 2号项目 各占据两个单元格,然后在默认的 grid-auto-flow: row
情况下,会产生下面这样的布局。
1号项目 后面的位置是空的,因为 1号项目 的后方不够 2号项目 放置,并且 3号项目 默认跟着 2号项目,所以会排在2号项目后面。
1 | <div class="grid box-8"> |
1 | .box-8 { |
将 grid-auto-flow
的值设置为 row dense
后,表示 “先行后列”,并且尽可能紧密填满,尽量不出现空格。
如果将设置改为 column dense
,表示 “先列后行”,并且尽量填满空格。
项目在单元格中的对齐方式
justify-items
设置项目在单元格中水平方向上的位置(左 start 中 center 右 end 拉伸(默认) stretch)。
align-items
设置项目在单元格中垂直方向上的位置(左 start 中 center 右 end 拉伸(默认) stretch)。
1 | start:对齐单元格的起始边缘。 |
place-items
place-items
属性是 align-items
属性和 justify-items
属性的合并简写形式。
1 | place-items: [align-items] [justify-items]; |
单元格的内容左对齐,效果如下图。
1 | justify-items: start; |
单元格的内容头部对齐,效果如下图。
1 | align-items: start; |
项目在容器中的对齐方式
justify-content
justify-content
属性可以定义整个内容区域在容器里面的水平放置位置(左中右)。
align-content
align-content
属性可以定义整个内容区域在容器里面的垂直放置位置(左中右)。
上面两个属性都可以使用如下值:
1 | start : 网格线开始位置,靠左或靠上。 |
这两个属性的写法完全相同,都可以取下面这些值。(下面的图都以
justify-content
属性为例,align-content
属性的图完全一样,只是将水平方向改成垂直方向。)
- start 对齐容器的起始边框。
- end : 网格线结束位置,靠右或靠下。
- center : 垂直或水平居中。
- stretch : 项目大小没有指定时,拉伸占据整个网格容器。
- space-around : 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与容器边框的间隔大一倍。
- space-between : 项目与项目的间隔相等,项目与容器边框之间没有间隔。
- space-evenly : 项目与项目的间隔相等,项目与容器边框之间也是同样长度的间隔。
place-content
place-content
属性是 align-content
属性和 justify-content
属性的合并简写形式。
1 | place-content: [align-content] [justify-content]; |
grid-auto-columns
grid-auto-rows
grid-auto-columns
和 grid-auto-rows
属性用来设置,浏览器自动创建的多余网格的列宽和行高。用法和 grid-template-columns 、grid-template-row
一毛一样。
1 | <div class="box-11 grid"> |
1 | .box-11 { |
如上图所示,区域 1 占据了 2 个单元格,导致第6个单元格无法放置在原本的网格内,浏览器自动根据第6块内容的大小创建了一个单元格。该单元格的宽高取决于这块内容自身的大小。
当我们设置了 grid-auto-columns
和 grid-auto-rows
属性时,浏览器则会根据这两个属性值去生成多余单元格的大小。
1 | .box-11 { |
如下图:
grid-template
grid-template
属性是 grid-template-columns、grid-template-rows
和 grid-template-areas
这三个属性的合并简写形式。
grid
grid
属性是 grid-template-rows、grid-template-columns、grid-template-areas、grid-auto-rows、grid-auto-columns、grid-auto-flow
这六个属性的合并简写形式。
函数
minmax()
使用 minmax()
函数约定长度范围。
1 | <div class="grid box-1"> |
1 | .box-1 { |
上方代码规则定义了 1*3
的网格,第 3 列单元格 使用了 minmax()
函数定义该列的列宽规则。表示,最小有 200px
宽,最大有 容器总宽度的 1/3
。如下图,当缩小容器宽度的时候,前 2 列的宽度值由于是相对单位,会进行适应缩放,而第 3 列 则会 最小保持 200px
的列宽。
repeat()
repeat()
函数可以某个值的次数。通常作用于 grid-template-rows
和 grid-template-columns
。
第一个参数:重复的次数。第二个参数:要重复的值。
1 | <div class="grid box-3"> |
1 | .box-3 { |
上面代码规则等同于:
1 | .box-3 { |
也可以使用 repeat() 函数重复某种模式。第一个参数:重复模式的次数。第二个参数:要重复的模式。
1 | .box-4 { |
1 | <div class="grid box-4"> |
关键字
auto-fill
使用 auto-fill
关键字 控制自动填充。
如下代码规则,列数自动填充,直到放不下为止,且每列的宽度为 200px。
1 | <div class="grid box-5"> |
1 | .box-5 { |
fr
使用 fr 关键字表示比例关系。
如下代码规则,第二列为第一列的2倍宽。
1 | <div class="grid box-6"> |
1 | .box-6 { |
fr 与 绝对单位 结合使用。第一列为固定宽度 200px,第3列宽为第2列的2倍。
1 | <div class="grid box-7"> |
1 | .box-7 { |
fr 之 圣杯布局
1 | <div class="grid box-8"> |
1 | .box-8 { |
auto
auto
关键字,表示由浏览器自己决定宽度。
如下,第1、3列为固定100px宽度,中间的第2列宽度由浏览器自动计算,即自适应。
1 | <div class="grid box-2"> |
1 | .box-2{ |
项目规则
下面这些规则定义在项目上面。
grid-row-start
grid-row-end
grid-column-start
grid-column-end
项目的位置是可以指定的,具体方法就是指定项目的四个边框,分别定位在哪根网格线。
1 | grid-row-start 用来设置 `上边框` 所在的网格线位置。 |
1 | <div class="grid box box-1"> |
1 | .box { |
如上图:1号项目的左边框被设置在第2根垂直网格线上,右边框被设置在第4根垂直网格线上。使得 1 号项目横跨了 第2、3个单元格。
剩余项目则跟在其后自动排布。这时它们的位置由容器的 grid-auto-flow
属性决定,这个属性的默认值是 row
,因此会”先行后列”进行排列。
这四个属性的值,除了指定为第几个网格线,还可以指定为网格线的名字。
1 | .item-1 { |
这四个属性的值还可以使用 span
关键字,表示 “跨越”,即左右边框(上下边框)之间跨越多少个网格。
1 | <div class="grid box box-2"> |
如上图:第一个项目横跨了第一个和第二个单元格。
这与下面代码效果一样:
1 | .item-1 { |
使用这四个属性,如果产生了项目的重叠,则使用 z-index
属性指定项目的重叠顺序。
grid-column
grid-row
grid-column
属性是 grid-column-start 和 grid-column-end
的合并简写形式,grid-row
属性是 grid-row-start 和 grid-row-end
的合并简写形式。
下面是一个例子:
1 | .item-1 { |
这两个属性之中,也可以使用 span
关键字,表示跨越多少个网格。
1 | .item-1 { |
斜杠以及后面的部分可以省略,默认跨越一个网格。
1 | .item-1 { |
上面代码中,项目item-1占据左上角第一个网格。
grid-area
grid-area
属性指定项目放在哪一个区域。
1 | <div class="grid box-4"> |
1 | .box-4 { |
如上图:将 1 号项目放置在 e 区域中。
项目中内容的对齐方式
justify-self
设置单元格内容的水平位置(左中右),只作用于单个项目中。
align-self
设置单元格内容的垂直位置(上中下),只作用于单个项目中。
这两个属性都可以去下面这些值:
1 | start:对齐单元格的起始边缘。 |
下面是 justify-self: start
的例子:
place-self
align-self
和 justify-self
的简写属性。
1 | place-self: [align-self] [justify-self]; |
如果省略第二个值,place-self
属性会认为这两个值相等。