grid布局
基本格子
<div class="box">
<div class="item1">item1</div>
<div class="item2">item2</div>
<div class="item3">item3</div>
<div class="item4">item4</div>
<div class="item5">item5</div>
</div>
.box {
display: grid;
}
父元素设置grid,只有第一级的子元素会受到grid布局影响,默认情况下,子元素的宽度都会占据一整行的宽度。哪怕子元素是一个inline
元素。
控制每列的格子宽度
grid可以理解为把table布局的功能提取为css了,并且加以改进,更加适合现代化的复杂布局。
那么既然是table,自然可以配置每行有多少个格子,每个格子的大小了,这个配置会影响到每列对应的格子,效果和控制table的th宽度一样,th宽度会影响到它下面的tbdoy的td宽度。
.box {
display: grid;
grid-template-columns: 200px 150px 20%;
}
这里表示每行有三个格子,每个格子对应的宽度分别为:200px 150px 20%
;当页面宽度足够的时候,右侧会出现空白,不会有元素像流体布局那样自动再后面追加,这也符合table布局的情况。
自适应宽度
如果我想占据剩余的宽度,我们可以使用fraction
;这个单位和flex的flex-grow
有异曲同工之处,都是占据剩余宽度,根据大小来进行等比分配。
.box {
display: grid;
grid-template-columns: 200px 2fr 20% 1fr;
}
这就表示第二个格子和第四个格子会占据剩余的宽度,并且按照2:1的比例分配。
控制每行的高度
.box {
display: grid;
grid-template-columns: 200px 2fr 20% 1fr;
grid-template-rows: 50px 30px;
}
这里表示两行格子,第一行50px高,第二行30px高;
如果有第三行,此时我们没有设置,那么就会遵循默认设置,一般是内容多高就多高。
占据剩余高度
同样也是使用fraction
;但是需要注意的是,父级有设置高度或者它有“高度”,而不是靠内容撑起来的,不然是无效的。
.box {
height: 100vh;
display: grid;
grid-template-columns: 200px 2fr 20% 1fr;
grid-template-rows: 50px 30px 1fr;
}
合并格子
其实和table的合并格子差不多,只是grid的合并,是需要配置分割线序号的。
浏览器开启显示序号更方便grid调试。
假如我们需要item3占据item4的位置
.item3 {
background-color: burlywood;
grid-column-start: 3;
grid-column-end: 5;
}
假如我们还需要item3往下占据一行
.item3 {
background-color: burlywood;
grid-column-start: 3;
grid-column-end: 5;
grid-row-start: 1;
grid-row-end: 3;
}
控制占据的分割线起始位置来达到效果,有点像js里字符串的截取,字符是从0开始,他这是从1开始。
auto 弹性系数
如果我们设置一些固定的行数或者列数,希望最后一个或者某一个能自动填满,那么一般推荐使用auto
;
但是多个auto他们不一定是等比分配的,所以,如果你有多个需要等比分配,fraction
更加适合
.box {
display: grid;
grid-template-columns: 200px 150px 20% auto;
grid-template-rows: 50px auto;
}
如果fraction
和auto
同时存在,fraction
权重会更大,因为auto代表剩余,但是剩余其实已经被fraction
占用了,如果格子没有内容,auto会导致格子宽或者高为0;
常用的两个css函数
重复repeat
grid-template-columns
设置几个就有几列,如果我想要5个相同大小的格子,那么就要写5次。
.box {
display: grid;
grid-template-columns: 20% 20% 20% 20% 20%;
}
利用repeat
函数我们可以很方便的创建
.box {
display: grid;
grid-template-columns: repeat(5, 20%);
}
命名网格线
这个知识点可以看完下面的命名网格线再来看,这里是关于repeat
与命名的使用。
由于repeat是重复,如果我们这么写:
.box {
display: grid;
grid-template-columns: repeat(5, [col-start] 20% [col-end]);
}
实际上会使得网格线的名称发生了重复,大概生成了如下的结构:
[col-start] [col-end col-start] [col-end col-start] [col-end col-start] [col-end col-start] [col-end]
生成这么6条线,且名字都是一样,这在使用的时候怎么区分?
css的做法是,如果名字一样,后面再接一个它的顺序,比如我要第二条col-start开始到第二条col-end结束,那么就需要这么写:
.item3 {
background-color: burlywood;
grid-column-start: col-start 2;
grid-column-end: col-end 2;
}
最小最大minmax
如果我们希望有一个格子,它的最小是10px;最大是200px;我们常常会使用:min-height、max-height
这种形式,利用函数我们可以很简单的配置
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(5, 20%);
grid-template-rows: minmax(50px, 200px) minmax(100px, 1fr);
}
minmax
第一个参数是最小值,第二个是最大值,当空间足够,就会使用最大值,不够则使用最小值,当已经不能再小的时候,就会固定,不会在继续缩小了。
这个效果有点像我们平时这么设置:
.container {
width:200px;
max-width: 1200px;
}
合并格子补充
指定合并的格子数量
合并格子的end参数可以像table那样,直接指定合并几格子
.item3 {
background-color: burlywood;
grid-column-start: 3;
grid-column-end: span 2;
grid-row-start: 1;
grid-row-end: span 2;
}
span表示合并格子,后面接合并的数量。
-1值
如果想让一个格子占据一行,我们可以可以使用-1
值,在不知道每行有多少个格子的情况下。
.item2 {
background-color: aquamarine;
grid-column-start: 1;
grid-column-end: -1;
}
正数的1是从左边开始,负数的1是从右边开始。
重叠与层级
grid布局是支持元素重叠的,比如item3占据的上下两行,而item2只是横向占据一整行,那么grid会自动判断,item3的权重更高,item2就只能往下移动。
.item2 {
background-color: aquamarine;
grid-column-start: 1;
grid-column-end: -1;
}
.item3 {
background-color: burlywood;
grid-column-start: 3;
grid-column-end: span 2;
grid-row-start: 1;
grid-row-end: span 2;
}
因为item2没有设置row
的具体,那么就会被自动往下移动已符合css占据一行的要求,但是如果item也指定了row,那么就会发生重叠,且重叠的层级是根据html元素顺序来得,元素在后面,层级就越高,并且支持z-index
直接控制层级。
.item2 {
background-color: aquamarine;
grid-column-start: 1;
grid-column-end: -1;
grid-row-start: 2;
grid-row-end: 3;
}
.item3 {
background-color: burlywood;
grid-column-start: 3;
grid-column-end: span 2;
grid-row-start: 1;
grid-row-end: span 2;
}
grid一般是不允许重叠的,如果需要重叠,我们就需要像上面那样指定固定位置。
由于item3在item2后面,所以重叠时他在上面,我们可以给item2指定z-index
层级,让他显示在上面。
.item2 {
background-color: aquamarine;
grid-column-start: 1;
grid-column-end: -1;
grid-row-start: 2;
grid-row-end: 3;
z-index: 1;
}
命名网格线
网格线是有序号的,但是我们可以为其自定义命名,且同一条线可以有多个名字,做法就是数值前面用[名字]
设置。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(3, 20%) auto;
grid-template-rows: [row-start] minmax(50px, 200px) [row-center row-bottom] minmax(100px, 200px) [row-end];
}
多个命名用空格分割,命名设置好后,就可以使用名称来定义范围了
.item3 {
background-color: burlywood;
grid-column-start: 3;
grid-column-end: span 2;
grid-row-start: row-start;
grid-row-end: row-end;
}
简写
grid-column为简写形式,第一个值为start,第二值为end,用/
分隔。
.item3 {
background-color: burlywood;
/* grid-column-start: 3;
grid-column-end: 5; */
grid-column: 3 / 5;
}
grid-row也是一样。
.item3 {
background-color: burlywood;
/* grid-row-start: 1;
grid-row-end: -1; */
grid-row: 1 / -1;
}
grid-column和grid-row也能合并成简写形式,只不过对顺序有要求
grid-area: grid-row-start / grid-column-start / grid-row-end / grid-column-end;
.item3 {
background-color: burlywood;
grid-area: 1 / 3 / -1 / 5;
}
行间距与列间距
行间距
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(3, 20%) auto;
grid-template-rows: 50px 100px;
grid-row-gap: 20px;
}
grid-row-gap只接受一个值,每行的间隔都是统一的
列间距
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(3, 20%) auto;
grid-template-rows: 50px 100px;
grid-column-gap: 20px;
}
一样也是只支持一个值。
简写
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(3, 20%) auto;
grid-template-rows: 50px 100px;
grid-gap: 20px 20px;
}
grid-gap
第一个值是行间距,第二个值是列间距,如果两个值一样可以只写一个。
命名区域
我们可以为每个格子命名,相同命名的格子则为一个整体,然后可以利用grid-area: 命名;
的形式,将元素快速定位到对应的格子中,且此时的排列顺序就不会根据dom顺序排列,而是grid自动排序,如果有空隙,会将后面的元素移动到空隙部分,如果能放下的话。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(3, 20%) auto;
grid-template-rows: 50px 100px;
grid-gap: 20px 20px;
grid-template-areas: "header header sidebar sidebar"
"main main footer footer";
}
.item1 {
background-color: blanchedalmond;
grid-area: header;
}
.item2 {
background-color: aquamarine;
grid-area: sidebar;
}
.item3 {
background-color: burlywood;
grid-area: main;
}
.item4 {
background-color: darkcyan;
grid-area: footer;
}
.item5 {
background-color: darksalmon;
}
grid-template-areas
配置格子命名,每行用引号包裹,可以单引号或者双引号,如果不想命名,可以用.
代替。
grid-template-areas: "header header sidebar sidebar"
". . footer footer";
使用时,给子元素配置命名即可:grid-area: footer;
如果使用了不存在的命名,格子就会发生变化和错乱。
注意: 如果我们配置了name,就可以勾选浏览器的显示name选项,可以很方便的看到每个格子的名称,这种方式可以很方便的进行布局使用。
自动推断网格命名
这个功能可能用的比较少,而且设置上比较繁琐,估计不会有很多人这么用。
grid支持自动推断网格名称,前提是网格线的命名必须要以:xxx-start、xxx-end
这种命名方式,且xxx
必须是相同的名字。
.box {
height: 100vh;
display: grid;
grid-template-columns: [hd-start] repeat(3, 20%) auto [hd-end];
grid-template-rows: [hd-start] 50px [hd-end] 100px;
grid-gap: 20px 20px;
}
我们给四个格子都在hd
的范围,然后第一行也是hd
;那么我们使用时就可以将hd
作为一个网格命名来使用
.item1 {
background-color: blanchedalmond;
grid-area: hd;
}
子元素水平对齐
grid也和flex一样控制子元素的水平对齐方式。但是控制的是元素所在格子范围内的水平对齐。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(5, calc(20% - 20px));
grid-template-rows: 100px;
grid-gap: 20px;
justify-items: center;
}
justify-items
的属性有:
- stretch 默认效果
- center 水平居中对齐
- start 水平起始点对齐
- end 水平结尾对齐
- 更多自己查文档
除了stretch,其他的对齐都会使得子元素默认占满格子宽度的效果失效。可以给子元素添加wdith:100%
来占满宽度。
注意: start和end不等同于left和right,它们会跟随文档的阅读方向改变而改变,默认是从左到右,有的国家是从右到左
子元素垂直对齐
控制的是元素所在格子范围内的垂直对齐
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(5, calc(20% - 20px));
grid-template-rows: 100px;
grid-gap: 20px;
align-items: center;
}
align-items
的属性有:
- stretch 默认效果
- center 垂直居中对齐
- start 垂直起始点对齐
- end 垂直结尾对齐
- 更多自己查文档
整体内容水平对齐
这个就是控制整个元素在grid中的水平对齐方式。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(7, 100px);
grid-template-rows: 100px;
grid-gap: 20px;
justify-content: center;
}
justify-content
的属性有:
- stretch 默认效果
- center 水平居中对齐
- start 水平起始点对齐
- end 水平结尾对齐
- 更多自己查文档
整体垂直对齐
这个就是控制整个元素在grid中的垂直对齐方式。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(7, 100px);
grid-template-rows: 100px;
grid-gap: 20px;
align-content: center;
}
align-content
的属性有:
- stretch 默认效果
- center 垂直居中对齐
- start 垂直起始点对齐
- end 垂直结尾对齐
- 更多自己查文档
单独控制子元素自己再格子内的对齐方式
这点和flex的有些相同的,但是grid的只能控制元素在格子范围内的对齐方式。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(7, 100px);
grid-template-rows: 100px;
grid-gap: 20px;
align-content: center;
justify-content: center;
}
.item2 {
background-color: aquamarine;
justify-self: start;
align-self: start;
}
justify-self
和align-self
的值都上面那些一样,具体也可以自己去查文档。
媒体查询的响应式处理
格子的大小数量都是定死的,如果随着设备的变化,pc端到移动端,宽度会越来越小,如果我们想让某些格子发生响应式变化,就需要重新增删格子的配置。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(4, 100px);
grid-template-rows: 100px 200px;
grid-gap: 20px;
grid-template-areas: "header header header header"
"sidebar sidebar main main";
}
@media (max-width: 768px) {
.box {
grid-template-rows: 100px 100px 200px;
grid-template-areas: "header header header header"
"sidebar sidebar sidebar sidebar"
"main main main main";
}
}
这里以自定义命名区域为例,通过响应式调整命名区域和row数量,子元素对应使用的命名区域定位,响应式触发时,元素位置也会发生变化。
控制grid自动添加格子的默认行为
当我们新增的元素已经超出格子的数量时,他会自动生成新的一行,并且每行的高度在没有配置的情况,以内容高度最高的那个格子为基准,这点和table效果是一样的。
我们可以控制自动生成的每行高度。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(4, 100px);
grid-template-rows: 100px 200px;
grid-gap: 20px;
grid-auto-rows: 100px; /*控制自动生成每行的高度*/
}
控制自动生成为列
默认情况下超出控制的元素会自动生成的row来包裹,但是我们可以控制它的行为。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(4, 100px);
grid-template-rows: 100px 200px;
grid-gap: 20px;
grid-auto-flow: column; /*控制自动生成列*/
}
这样设置元素就不会往下排列,而是往右边生成列了。
控制自动生成列的宽度
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(4, 100px);
grid-template-rows: 100px 200px;
grid-gap: 20px;
grid-auto-flow: column; /*控制自动生成列*/
grid-auto-columns: 100px;
}
简单布局原理总结
从以上的css配置来看,我们可以明确的知道,格子是有两种配置的,一种是显式配置,也就是通过grid-template-columns
和grid-template-rows
显式声明格子数量大小的,一种是隐式配置,他会将超出配置的元素安排在自动生成的格子配置上,虽然这个配置我们也可以插手进行修改。
但是这个很重要,这对于我们记住grid的布局原理很有帮助。
自动换行
比较常见的一个功能,但是grid默认配置是定死的,但是我们希望的时,在一个固定格子大小的情况下,格子能根据页面的大小自动排列换行。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
grid-template-rows: 100px 200px;
justify-content: center;
}
auto-fill
的作用是让元素尽可能的占满一行,且列的宽度都是300px
;
可以看到当一行宽度不够时,元素会自动换行,并且是左对齐状态(水平对齐失效)。
我们还可以使用auto-fit
;该属性效果等同于auto-fill
;但是auto-fill会导致justify-content
对齐失效,而使用auto-fit
;会在换行时保留justify-content的效果。
.box {
height: 100vh;
display: grid;
grid-template-columns: repeat(auto-fit, 300px);
grid-template-rows: 100px 200px;
justify-content: center;
}
空白行为
当一行的格子不能满足某一个格子的宽度要求时,这个格子会被自动换行。但是上一行空出的位置,不会有元素去占据。
.box {
width: 900px;
height: 100vh;
display: grid;
grid-template-columns: repeat(3, 300px);
grid-template-rows: 100px 200px;
}
.item1 {
background-color: blanchedalmond;
grid-column: span 2;
}
.item2 {
background-color: aquamarine;
grid-column: span 2;
}
css中我们设置每行有3个格子,但是item1和item2都要占据两个格子,这就导致第一行格子数量不满足需要,item2被换行处理了。
有啥办法可以让这个空白占满呢?
答案是有的,我们可以控制自动生成row时的行为,利用grid-auto-flow
配置。
.box {
width: 900px;
height: 100vh;
display: grid;
grid-template-columns: repeat(3, 300px);
grid-template-rows: 100px 200px;
grid-auto-flow: row dense;
}
grid-auto-flow
默认值是row
,后面接dense
表示改变跳过空白的这种行为,这就可以让后面的格子去占据空白的部分。
当然column
也可以加这个属性。
grid-auto-flow: column dense;
注意:
虽然我们可以控制这个空白的行为,但是并不建议这么做,因为这会导致正常用户与无障碍用户产生阅读上的问题。
正常用户看到的元素顺序是:1、3、2、4、5
而无障碍用户它的阅读顺序是根据dom顺序来阅读的:1、2、3、4、5
结语
至此grid的布局基本结束,我们需要考虑的是grid与flex布局,它的合理使用。
如果一个布局,我们只需要考虑单向的排列布局,那么flex更加合适,而grid适合更加复杂的情况,比如ui框架中的row布局,其实用grid会更加便捷。
本文系作者 @木灵鱼儿 原创发布在木灵鱼儿站点。未经许可,禁止转载。
暂无评论数据