grid布局 和 flex布局的区别
Flex 布局是轴线布局,只能指定"项目"针对轴线的位置,可以看作是一维布局。
Grid 布局则是将容器划分成"行"和"列",产生单元格,然后指定"项目所在"的单元格,可以看作是二维布局。Grid 布局远比 Flex 布局强大。
Grid 布局的基本术语
- 容器——采用网格布局的区域
- 项目——容器内采用网格定位的子元素(项目只能是容器的顶层子元素,不包含项目的子元素,如下方代码的
<p>
元素就不是项目。Grid 布局只对项目生效。)
<div>
<div><p>1</p></div>
<div><p>2</p></div>
<div><p>3</p></div>
</div>
上面代码中,最外层的<div>
元素是容器,内层的三个<div>
元素是项目。
网格布局的使用方法
启用网格布局
块级容器时
display: grid;
行内容器时
display: inline-grid;
使用网格布局后,项目的float
、display: inline-block
、display: table-cell
、vertical-align
和column-*
等设置都将失效。
划分列 grid-template-columns
绝对值 px
在容器内划分出3列,每列宽度为100px
grid-template-columns: 100px 100px 100px;
百分比值 %
将容器等分为3列,每列宽度为容器总宽度/3
grid-template-columns: 33.33% 33.33% 33.33%;
比例值 fr
将容器划分为2列,第1列的宽度 :第2列的宽度 = 1:2
grid-template-columns: 1fr 2fr;
fr 是fraction 的缩写,意为"片段",可以与绝对长度的单位结合使用
grid-template-columns: 150px 1fr 2fr;
第一列的宽度为150像素,第二列的宽度是第三列的一半
- 如果所有fr值之和大于1,则按fr值的比例划分可自动分配尺寸。
- 如果所有fr值之和小于1,最终的尺寸是可自动分配尺寸和fr值的乘法计算值。
和auto关键字混合使用
grid-template-columns: auto 1fr 1fr 1fr;
fr值的可自动分配尺寸是容器尺寸减去设置auto关键字的列的fit-content尺寸。在本例中,由于设置auto关键字的这一列里面内容比较少,fit-content尺寸就是这几个字符的宽度尺寸,因此,最终的尺寸表现就是最后3列按照1:1:1的比例平分了容器尺寸减去“宽度auto”这几个字符的宽度得到的尺寸。
minmax()函数值
minmax()
函数产生一个长度范围,表示长度就在这个范围之中。它接受两个参数,分别为最小值和最大值。
grid-template-columns: 1fr 1fr minmax(100px, 1fr);
minmax(100px, 1fr)
表示列宽不小于100px
,不大于1fr
。
repeat()
函数值
repeat()
接受两个参数,第一个参数是重复的次数,第二个参数是要重复的值。
grid-template-columns: repeat(3, 33.33%);
grid-template-columns: repeat(2, 100px 20px 80px);
上方代码定义了6列,第一列和第四列的宽度为100px
,第二列和第五列为20px
,第三列和第六列为80px
。
无法确定列数时,重复次数使用关键字:auto-fill 或 auto-fit
.container {
grid-template-columns: repeat(auto-fill, 100px);
}
.container {
grid-template-columns: repeat(auto-fit, 100px);
}
关键字往往会和其他网格布局函数一起使用,例如minmax()函数
.container {
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
这就实现了无论grid容器多宽,grid子项都会等比例充满grid容器(因为设置了1fr),同时保证宽度不小于100px,网格布局的列数自动计算分配的智能弹性布局效果。
使用auto-fill关键字自动填充的时候,repeat()函数不能和auto一起使用的,但可以与长度值和百分比值一起使用。
.container {
/* 有效 -- 每一行的最后一列的宽度都会是容器的20%大小 */
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr))20%;
}
使用auto-fit关键字实现的布局效果要比auto-fill关键字实现的更符合常规的布局需求
fit-content()函数
让尺寸适应于内容,但不超过设定的尺寸,常用于希望grid子项的宽度随着内容变化,但是又不希望宽度太大的场景。
.container {
display: grid;
grid-template-columns: fit-content(100px) fit-content(100px) 40px auto;
}
fit-content()函数只支持数值和百分比值,fr值是不合法的。
min-content
最小内容尺寸中最大的那个最小内容尺寸值。网格布局中的同一行grid子项的高度和同一列grid子项的宽度都是一致的,因此min-content指的并不是某一个格子的最小内容尺寸,而是一排或者一列格子中所有最小内容尺寸中最大的那个最小内容尺寸值。
max-content
max-content关键字和min-content关键字类似,只是最终的尺寸是最大内容宽度中最大的那一个值。
auto
由浏览器自己决定长度
尺寸的上限是最大内容尺寸的最大值,但是不同于max-content关键字,max-content关键字的尺寸是固定的,这里的尺寸是会受到justify-content属性和align-content属性影响的。
grid-template-columns: 100px auto 100px;
第二列的宽度,基本上等于该列单元格的最大宽度,除非单元格内容设置了min-width
,且这个值大于最大宽度。
划分行 grid-template-rows
使用方法与列相同
grid-template-rows: 100px 100px 100px;
或
grid-template-rows: 33.33% 33.33% 33.33%;
.container {
grid-template-columns: 80px auto 100px;
grid-template-rows: 25% 100px auto 60px;
}
自动填充 auto-fill
单元格大小固定,但容器大小不确定时,如果希望每一行(或每一列)容纳尽可能多的单元格,可以使用auto-fill
关键字进行自动填充。
grid-template-columns: repeat(auto-fill, 100px);
每列宽度100px
,然后自动填充,直到容器不能放置更多的列。
给网格线命名 []
在grid-template-columns
属性和grid-template-rows
属性中,使用方括号指定每一根网格线的名字,方便以后的引用。
.container {
display: grid;
grid-template-columns: [c1] 100px [c2] 100px [c3] auto [c4];
grid-template-rows: [r1] 100px [r2] 100px [r3] auto [r4];
}
上面代码指定网格布局为3行 3列,因此有4根垂直网格线和4根水平网格线。方括号里面依次是这八根线的名字。
由于网格的中间区域的网格线是由两边格子公用的,因此,可以给网格线起两个名称(使用空格分隔),分别表示网格线的两侧。
.container {
grid-template-columns: [广告区-左] 120px [广告区-右 内容区-左] 600px [内容区-右];
}
设置行/列的间距
设置行间距 row-gap
row-gap: 20px;
支持数值和百分比值
设置列间距 column-gap
column-gap: 30px;
支持数值和百分比值
gap是column-gap
和row-gap
合并的简写形式
gap: 20px 30px;
如果gap
省略了第二个值,浏览器认为第二个值等于第一个值。
支持数值和百分比值和calc()函数
指定区域 grid-template-areas
可以将网格布局中的某个单元格或多个单元格定义为一个区域
网格区域一定要形成规整的矩形区域,无论是L形,还是凹的或凸的形状都会认为是无效的属性值。
区域的命名会影响到网格线。每个区域的起始网格线,会自动命名为区域名-start,终止网格线自动命名为区域名-end。比如,区域名为header,则起始位置的水平网格线和垂直网格线叫做header-start,终止位置的水平网格线和垂直网格线叫做header-end。
.container {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
grid-template-areas: 'a b c'
'd e f'
'g h i';
}
上面代码先划分出9个单元格,然后将其定名为a
到i
的九个区域,分别对应这九个单元格。
不属于任何区域的单元格,用.表示
grid-template-areas: 'a . c' 'd . f' 'g . i';
多个单元格合并成一个区域
grid-template-areas: "header header header"
"main main sidebar"
"footer footer footer";
上面代码中,顶部是页眉区域header
,底部是页脚区域footer
,中间部分则为main
和sidebar
。