L o a d i n g . . .
SHIWIVI-文章

//sunny forever
while(life<end){
love++;
beAwesome :)}

    <
  • 主题:
  • + -
  • 清除背景
  • 禁用背景

Grid栅格布局

字数:10592 写于:2022-06-14
最新更新:2022-06-14 阅读本文预计花费您31分钟
Grid在MDN上翻译为网格布局,在《CSS权威指南》中翻译为栅格布局,其实是同一种布局方案,本文语句主要整理自《CSS权威指南》一书

1. 栅格布局

Grid 是一种强大的布局方案,也是最为普适的布局方案,允许在Web上创建二维布局,通过对父元素定义不同参数的行与列垂直线,再将子元素部署于行列网格上,由此实现各类灵活的布局,如:

box1
box2
box3
box4
box5

通过标准流、float、flex也可以实现类似的布局,但这些方案往往需要更多的DOM元素,或者需要指定更多的参数,并且很多情况下无法做到自适应,此时,grid布局方案的优势就体现出来了。并且语法兼容性也很好,除了那位大爷…..

ChromeEdegFirefoxIEOperaSafari
571652不支持4410.1

2. 栅格容器

创建栅格的第一步就是创建一个栅格容器,并将其中的内容定义为栅格布局

2.1 栅格属性

display: grid/inline-grid;

指定容器布局方式为栅格布局,该属性和 block 与 inline-block 值相似

2.2 定义栅格模板

grid-template-columns: 值;

grid-template-rows: 值;

将容器划分为行列栅格,栅格线的值可以为固定值百分比fr关键字repeat()语句minmax()语句calc()函数等,并且参数可以混用

2.2.1 固定值行列轨道宽度

将子元素宽高设为固定值,单位可以为px,也可以为em、rem等相对单位

如:给父元素指定行列轨道宽度,子元素可以不设置任何参数 div{ display:grid; grid-template-columns:50px 60px 100px; grid-template-rows:50px 60px 100px; }
box1
box2
box3
box4
box5
box6
box7
box8
box9
类似的取值可以为 grid-template-columns:5em 5em 5em;
2.2.2 百分比配置宽高

将元素的宽高按百分比配置,可以让网页元素自适应不同屏幕大小

如:元素宽高分别为20% 20% 50% div{ display:grid; grid-template-columns:20% 20% 50%; grid-template-rows:20% 20% 50%; border:1px solid black; box-sizing: border-box; }
box1
box2
box3
box4
box5
box6
box7
box8
box9
百分比是基于父容器的宽度和高度计算,不管子元素内容大小如何变化也不会变,因此要给与父元素宽高参数,即不能再使用子元素撑开父元素了。若子元素宽高相加不到100%,则剩余部分空置
2.2.3 fr按比例配置宽高

grid布局提供了 fr 关键字(fraction)用于表示比例关系

如:元素宽高比为1:2:2 div{ display:grid; grid-template-columns:1fr 2fr 2fr; grid-template-rows:1fr 2fr 2fr; border:1px solid black; box-sizing: border-box; }
box1
box2
box3
box4
box5
box6
box7
box8
box9
配合其他值来实现弹性布局 grid-template-columns:150px 1fr 10%; 第一列宽为150px,最后一列宽为10%,剩下宽度给中间一列
2.2.4 定义栅格线名称

可以使用[ ]为边框线起名字,并且同一条线的名称可以有无数多个,如:[a1 b1]为同一条线取名a1和b1

如:元素宽高比为1:2:2 div{ display:grid; grid-template-columns: [c1] 80px [c2] 80px [c3] 80px [c4]; grid-template-rows: [r1] 60px [r2] 60px [r3] 60px [r4]; border:1px solid black; box-sizing: border-box; } box1、box4、box7左边框线相连为c1,右边框线相连为c2; box1、box2、box3上边框线相连为r1,下边框线相连为r2 其他以此类推
box1
box2
box3
box4
box5
box6
box7
box8
box9
2.2.5 repeat()重复填充

对于多个宽高值相同的元素,可以使用repeat()语句简写

如: 1. 对于grid-template-columns: 5em 5em 5em; 该语句可以简写为 grid-template-columns: repeat(3,5em); 2. 类似地可以创建宽度有一定规律的子元素 如:创建宽度依次为20px,40px,60px,20px,40px,60px的6列元素 grid-template-columns: repeat(2, 20px 40px 60px); 3. 还可以repeat()前后添加不想重复的宽高值 grid-template-columns: repeat(2,1em 5em) 2em; 这就生成了1em 5em 1em 5em 2em的网格 4. 百分号和比例依旧适用 grid-template-columns: repeat(3,33.3%); 5. 如果包含了栅格线名,名称也会被复制 grid-template-columns: repeat(3,[top] 5em [bottom]); 则会生成 [top] 5em [bottom top] 5em [bottom top] 5em [bottom] 即:中间的栅格线将会有两个名称,该语句等同于: grid-template-columns: [top] 5em [bottom top] 5em [bottom top] 5em [bottom];
2.2.6 minmax()限制尺寸

当子元素溢出父容器之外时,除了使用overflow: hidden;外,还可以使用minmax(最小值,最大值)来限制宽高尺寸

如:将剩余空间分配给第二列,但又要避免他被挤占得太小 grid-template-columns:5em minmax(10%,1fr) 2em;
注意!当minmax()中最大值小于最小值时,最大值将失效。如minmax(100px,2em)中,当2em计算值小于100px时,元素宽高将被解析为100px
2.2.7 calc()计算尺寸

grid是支持calc()语句的,只是有时候不太适用

如:第二列宽度通过计算得出 grid-template-columns:2em calc(100%-1.5em) 10%;
2.2.8 根据内容自适应

子元素宽高还可以根据子元素内容,通过max-contentmin-contentfit-content来实现栅格自适应

  • max-content:解析为尽可能大的空间,以防换行
  • min-content:解析为尽可能小的空间,能够显示内容即可
  • fit-content:解析为空间尽可能小,但如果超过指定空间大小就换行
如:尽可能容纳内容 div{ display:grid; grid-template-columns:max-content max-content max-content; grid-template-rows:max-content max-content max-content; } 可以看到,每一列的宽度由该列有最长内容的列宽决定,行类似。当父元素指定宽度时,这可能会溢出到父容器之外
1
22
33333333
44444444444
5
6
77
8888
9
配合minmax()使用可以不破坏外部布局,但会挤压内部空间 div{ display:grid; grid-template-columns:minmax(0,max-content) minmax(0,max-content) minmax(0,max-content); grid-template-rows:max-content max-content max-content; }
1
22
33333333
44444444444
5
6
77
8888
9
fit-content用于限制最大长度,类似于max-width 指定三列宽均为50等宽字符,当未满50ch时按实际字符长度算,超过该值则进行换行,即最大值只能为50ch div{ display:grid; grid-template-columns:fit-content(50ch) fit-content(50ch) fit-content(5.0ch); } 只指定宽度,高度自适应,第一第二列未满50ch时,以各自长度为列宽,第三列超过50ch,则进行换行,以50ch为列宽
the night
Avicii
He said one day you will leave this world behind So live a life you will remember
当父容器较小时,第一、第二列即便未满50ch也可能会进行换行,以保证不会溢出父亲容器
2.2.9 auto-fill自动填充

当父容器宽度固定,可以使用auto-fill让子元素根据大小自动填充

如: div{ display:grid; width:50vh; grid-template-columns:repeat(auto-fill,5em); grid-template-rows:max-content max-content max-content; } 在父容器中尽量排列宽3em的元素,排列到第一行排完,如果剩下空间不足3em,则剩余子元素将进行换行
box1
box2
box3
box4
box5
box6
box7
box8
box9
1. 一个父容器的宽/高只能有一次自动排列,因此下述语句是不允许的 grid-template-columns: repeat(auto-fill,5em) repeat(auto-fill,2em); 2. 但可以固定尺寸的repeat与自动填充的repear共存,如: grid-template-columns: repeat(2,5em) repeat(auto-fill,2em); 或者 grid-template-columns: repeat(auto-fill,5em) repeat(3,2em); 但无论语序如何,grid总会为固定尺寸的元素分配空间,因此auto-fill会被最后才被分配空间

2.3栅格间距

通过row-gapcolumn-gap来设置栅格见的行、列间隔。或者将两个属性合并为一个 grid-gap:行间隔 列间隔;

给父容器添加该属性 div{ display:grid; width:50vh; height:50vh; grid-template-columns:repeat(3,60px);grid-template-rows:repeat(3,60px); row-gap:10px; column-gap:10px; } 如图所见,添加间隔可能导致栅格溢出,这两个属性可合并为 grid-gap ,如果该语句之后的值只有一个,则解析为行列间隔都为该值。 grid-gap:10px 10px; 等价于 grid-gap:10px;
box1
box2
box3
box4
box5
box6
box7
box8
box9

3. 栅格区域

此前都是给父容器添加属性,但如果同时给子元素添加相应属性可以做出更好的布局

3.1 调用栅格线名

通过grid-template-columnsgrid-template-rows定义栅格宽高和栅格线名后,可以通过下列语句调用栅格线名

  • grid-column-start:列开始的栅格线名
  • grid-column-end:列结束的栅格线名
  • grid-row-start:行开始的栅格线名
  • grid-row-end:行结束的栅格线名
通过四条边来定义子元素的具体位置,当未定义栅格线名时,可以使用1,2,3...作为栅格线名 .box1 { grid-column-start:1; grid-column-end:2; grid-row-start:2; grid-row-end:4; background-color: #ff3426;//红色 } .box2 { grid-column-start:3; grid-column-end:5; grid-row-start:1; grid-row-end:3; background-color: #39f64f;//绿色 }

.parbox {
display:grid;
grid-template-columns: repeat(4,50px);
grid-template-rows: repeat(4,50px);
}
栅格线名可以为负数,表示从该栅格线往其反方向数

1. 栅格线的编号可以为负值,表示从倒数第n条线开始从后往前数 如:不知道栅格有几列,但想从最右边的栅格线开始部署,可以使用 grid-column-start:-1; grid-row-start:-1;(行同理) 2. 如果为栅格线定义过名称,则可以使用该名称作为上述语句的值,如果变量对应的栅格线有多条,则使用变量名 序号来确定具体的栅格线,序号从1开始排列。如:有多条名为col-A的线,表示列从第4条col-A开始: grid-column-start:col-A 4; 3. 此外可以使用span语句指定子元素跨越的行列数,如: .box1 { grid-column-start:1; grid-column-end: span 1; grid-row-start:2; grid-row-end: span 2; } 上述代码等同于: .box1 { grid-column-start:1; grid-column-end: 2; grid-row-start:2; grid-row-end: 4; } 表示该子元素从左边框号1开始,跨越1列,从上边框号2开始,跨越2行,其中span 1可以直接简写为span(默认为1),且span后的值不能为0负值 4. 当使用 span 栅格线名 n 时,表示该元素跨越了n条该名称的栅格线 如:栅格部署为A、B栅格线交替命名时 A 格子 B 格子 A 格子 B 格子 A 格子 B 格子 此时 grid-column-start: A 1; grid-column-end: span 2 A; 表示栅格从第1条A线开始,跨越1条名为A的栅格线,在下一个A线处结束

3.2 调用栅格线名的简写

上一节中 grid-column-start,grid-column-end和grid-row-start,grid-row-end用于指定栅格起始和结束的位置,该属性可以简写为

  • grid-column: 起始栅格线/结束栅格线
  • grid-row: 起始栅格线/结束栅格线
1. 元素开始和结束的栅格线名用 / 隔开 .box1 { grid-column-start:1; grid-column-end: 2; grid-row-start:2; grid-row-end: 4; } 等价于 .box1 { grid-column: 1 / 2; grid-row: 2 / 4; } 也可以用跨越了多少栅格表示 .box1 { grid-column: 1 / span 1; grid-row: 2 / span 2; } 2. 如果 / 和第二个值省略,则默认起始结束的栅格线名都一致 如:列栅格线中有两条名为header的线,则 grid-column: header; 等价于 grid-column: header / header; 即以第一条header开始,第二条header结束,无论中间跨越多少栅格

3.3 grid-area

grid-area可用于调用网格线,也可用于为子元素命名

3.3.1 grid-area调用网格线

grid-column-start,grid-column-end和grid-row-start,grid-row-end可以直接用一个语句代替:
grid-area:行开始/列开始/行结束/列结束

如: .box1 { grid-row-start:2; grid-row-end: 4; grid-column-start:1; grid-column-end: 2; } 等价于 .box1 { grid-area:2/1/4/2; } 同样,值可以为跨越了多少个网格 .box1 { grid-area: 2 / 1 / span 2 / span 1; }
3.3.2 grid-area为子元素命名

可以通过grid-area给每个栅格子元素定义名称,然后由父容器通过grid-template-areas定义它们的排列方法

如: .box1 { grid-area: a; } .box2 { grid-area: b; } .box3 { grid-area: c; } .box4 { grid-area: d; } .box5 { grid-area: e; } .parbox { display:grid; grid-template-areas: 'a a a'     'b c d'     'b e e'; } 排列方法可以写于同一行上,但需要注意' '号 grid-template-areas: 'a a a''b c d''b e e';
box1
box2
box3
box4
box5
变量名应该尽量使用有含义的单词 (子元素变量名应相应改变,这里只展示父容器属性) .parbox { display:grid; grid-template-areas: 'header header header''left content right''left footer footer'; } 也可以省略其中的部分变量,使用...代替 .parbox { display:grid; grid-template-areas: 'header header header''left ... right''left footer footer'; }

4. 栅格的对齐方式

栅格对齐方式类似于flex弹性盒里的属性

属性 目标 适用于
justify-self 行(一个栅格元素) 子元素
justify-items 行(所有栅格元素) 父容器
justify-content 行(整个栅格) 父容器
align-self 列(一个栅格元素) 子元素
align-items 列(所有栅格元素) 父容器
align-content 列(整个栅格) 父容器
以行为例 .box1{ justify-self:start; } .box2{ justify-self:center; } .box3{ justify-self:end; } justify-self和justify-items用来调整单个或多个元素在它们自己栅格内的位置 当justify-self赋值为start、center、end时,如果子元素没有指定宽度和高度,则会自动缩为仅合适内容的大小,对齐方式同单词含义。赋值为stretch时会被拉伸,完全填充box(同剩下的box) 当需要所有元素都有该对齐方式,则可以给父容器添加justify-items和对应的值
box1
box2
box3
box4
box5
box6
box7
box8
box9
同样以行为例 .parbox{ width:260px; height:260px; display:grid; grid-template-columns:repeat(3,80px);grid-template-rows:repeat(3,80px); justify-content:center; } justify-content则是用来调整整个grid网格在父容器中的位置
box1
box2
box3
box4
box5
box6
box7
box8
box9

5. 隐式栅格

此前通过grid-template-rows定义的栅格为显式栅格,当一部分栅格超出了显式栅格,系统会将超出的那部分定义为隐式栅格。可以使用grid-auto-rowsgrid-auto-columns定义隐式栅格的大小

如: .grid{ display:grid; width:200px; height:200px; //定义2*2的显式栅格 grid-template-columns:100px 100px; grid-template-rows:100px 100px; //定义隐式栅格尺寸(以行为例) grid-auto-rows: 50px; } box1、box2、box3、box4在显式栅格内,高为100px,box5,box6超出了显式栅格,高将变为隐式栅格的高50px
box1
box2
box3
box4
box5
box6



6. 栅格流

栅格流主要分为优先行、优先列、密集流三种模式,由grid-auto-flow决定

grid-auto-flow的取值有row、column、dense(密集流) .box{ display: grid; grid-template: repeat(3,80px) / repeat(3,80px); width: 240px; height: 240px; grid-auto-flow: row; } 优先行与优先列的部署模型如下
box1
box2
box3
box4
box5

box1
box2
box3
box4
box5
密集流的主要作用是让元素尽量靠紧,因此有时会破坏栅格元素的顺序进行密集分布,向任何可以插入的位置安插合适的子元素

7. 错误处理

当输入错误的代码时,部分情况下grid会帮我们修正属性,但在有些情况下会抛弃部分无法解析的值,甚至不解析整个语句

1. 当栅格开始线放在结束线后 grid-row-start:5; grid-row-end:2; grid将修正为 grid-row-start:2; grid-row-end:5; 2. 当栅格开始线和结束线都被声明为了跨度 grid-row-start: span ; grid-row-end: span 3; 结束线的值将被修改为 auto grid-row-start: span ; grid-row-end: auto; 3. 如果栅格开始线被声明为跨越已命名的线,则该语句将被认为非法 grid-row-start: span header;
当栅格元素出现重叠时,可以使用 z-index 或 order 进行排序,并且栅格元素可以使用margin、position等标准流、定位等属性。并且还有其他一些更复杂的属性简写语法,本文不再展开说明,具体可以查阅MDN的文档
上一篇:yaml语法
下一篇:Vux状态管理
z z z z z