JavaScript五十问——对比来说CSS的Grid与FlexBox(下篇)
发布日期:2021-06-24 18:22:42 浏览次数:2 分类:技术文章

本文共 8173 字,大约阅读时间需要 27 分钟。

前言

在上篇——,我介绍了Flex的属性与使用,今天我们来总结一下Grid的具体使用方法,最后会结合Flex与Grid布局讲一讲二者的联系与不同。

需要注意得是,Grid布局与我们之前所熟悉的css布局思路有很大的不同,阅读这篇文章之前,需要把我们平时对css的刻板印象抛弃掉,准备接受知识的洗礼吧,少年!

Grid

与 Flex 相同,Grid 也分为容器与元素两个概念;在一个 html 标签中添加样式:display:grid或者display:inline-grid,即构建了一个 Grid 的容器,里面的 dom 元素即为 Grid 元素。同样,Grid 也分为两类属性,分别装载在容器与元素上,下面一一说明。

HTML结构说明

以下所有例子均基于或扩展于下面的HTML结构:

 
1
2
3
4
5

Grid 基本概念介绍

网格

Grid容器里面有网格一系列的概念;听着唬人,但是结合图很容易理解。

网格线

水平方向有垂直方向的线段即为网格线

clipboard.png

网格轨道

两个相邻的平行网格线之间的区域就是网格轨道

clipboard.png

网格单元

四个相邻边组成的区域就是网格单元。

clipboard.png

fr

fr是Grid中特有表示尺寸的单位,是分数——fraction的缩写,假设我们现在有四个grid元素,每个元素的宽度都是1fr,那么每个元素的实际宽度就是总宽度的1/4。

fr也可以跟%,px 共同使用,他的计算规则就是刨去px与%的剩余空间作为fr分配空间,所有fr相加之和作为分母,分子为每个元素对应的fr的值。(当然,在Grid语境下,我们是不需要设置width属性的,这样说是为了让大家容易理解)。

这样说来好像fr仅仅是%的另外一种写法,随着我的介绍,你就会发现fr优于%的地方。

Grid属性脑图.png

接下来,我还是以脑图为思路介绍Grid的各个属性。

容器属性

grid-template

grid-tempalte是三个属性的简写,这三个属性都是描述整块区域即多个网格单元的属性。

grid-template-rows

grid-template-rows是描述横向单元轨道属性的。可以试想一下,我们在一个Grid容器中,关于这个属性,我们关心的是什么呢?无非就是这个容器中有多少行,每行的高度;所以,这个属性就是让我们定义这些值得。先来看语法:

grid-template-rows: <track-size> | <line-name> <track-size> ...;
这个属性除了可以定义轨道尺寸和个数之外,还允许我们定义两个轨道之间的网格线的名称,至于他的作用,我们先按下不表,先来看这个属性是怎样定义每个轨道的尺寸和轨道个数的。
先来看一个例子:

.container{    grid-template-rows:200px auto 1fr 1fr 20%;    grid-row-gap:10px;//定义轨道之间的间距}

grid-template-rows定义了五个值,表示Grid容器里面有五行,可以使用任意的定义尺寸的方式,效果如下

clipboard.png

其中auto值就表示元素的实际占用大小。

Grid分配空间首先计算除了fr对应轨道的尺寸,然后将剩余尺寸按照比例分配给fr加持的元素。
以上,我们在Grid容器里定义了五行容器轨道,当我们定义轨道过多时,可以使用repeat函数来减少我们的工作量,语法为:
grid-template-rows:repeat(n, size)
例子:

.container{    grid-template-rows:repeat(5,1fr);    grid-row-gap:10px;}

clipboard.png

上面就定义了五个网格轨道,每个轨道的高度是Grid容器高度的1/5。

grid-template-columns

grid-template-columns 与 grid-template-rows使用方法是一致的,这两个属性共同作用于Grid容器,相当于把Grid容器分割为m*n个子区域。

例子:

.container{    grid-template-rows:repeat(3,1fr);    grid-template-columns: repeat(2, 1fr)

上面这个例子就会得到六个均等分的子区域。

通过上面两个属性,相信大家对Grid布局有一个基本的认识了,想必对Grid二维布局的模式也有一些概念了,接下来才是Grid精彩之处,震撼灵魂的地方!

grid-template-areas

上面两个属性分别设置Grid行属性和列属性,grid-template-areas是设置Grid区域的。所谓区域是由一个或多个行、列、单元组成的一篇区域。首先看一下语法:

.container {  grid-template-areas:     "
| . | none | ..." "...";}

其中

grid-area-name表示网格区域的名称
.表示空的网格区域
none 表示没有定义网格区域
在我们平时开发时,经常会出现上头下尾中间两栏布局的情况,下面我们使用grid-template-areas完成这样的布局。

.container{  display:grid;  grid-template-rows:60px 1fr 60px;  grid-template-columns:100px 1fr;  grid-template-areas:    "header header"    "left right"    "footer footer";}.container .item:first-child{  grid-area: header;}.container .item:nth-child(2){  grid-area: left;}.container .item:nth-child(3){  grid-area: right;}.container .item:nth-child(4){  grid-area: footer;}.container{  display:grid;  grid-template-rows:60px 1fr 60px;  grid-template-columns:100px 1fr;  grid-template-areas:    "header header"    "left right"    "footer footer";}.container .item:first-child{  grid-area: header;}.container .item:nth-child(2){  grid-area: left;}.container .item:nth-child(3){  grid-area: right;}.container .item:nth-child(4){  grid-area: footer;}
1
2
3
4

在Grid容器中,我们定义了6个网格单元,使用grid-tempalte-areas划分了header footer left right 四片区域;而在grid元素中,每个元素使用grid-area来指定元素所对应的grid区域。因此,我们虽然划分了6个单元,但可以使用四个元素来表示。

clipboard.png

是不是很神奇呢,更神奇的是,grid-area-name是支持中文定义的。

以上grid-template的子属性就说完了,grid-template是以上那三个属性的简写方式,语法如下:

grid-tempalte:<'grid-template-rows'> / <'grid-template-columns'>``grid-tempalte:[ 
?
?
? ]+ [ /
]?

例如上面的例子可以这样简写

grid-template:     "header header" 60px    "left right" 1fr    "footer footer" 60px    / 50px 1fr;

grid-gap

grid-gap用来描述Grid 区域之间间隙的尺寸大小。语法如下:

.container {    grid-gap: 
;}

grid-gap是简写属性,也可以分别定义grid行间隔和grid 列间隔。

.container{    grid-row-gap:10px;    grid-column-gap:10px;}

grid-gap与margin与padding不同,它不占用当前元素的盒模型的位置。

clipboard.png

上图显示的很清楚,3号元素的margin 与 padding 均为零。

place-items

place-items justify-itemsalign-items的简写方式

这两个属性分别定义了Grid元素水平与垂直分布方式。
语法如下:

justify-items: stretch | start | end | center;    align-items: stretch | start | end | center;

对于这四个属性,默认stretch,相信读者在熟悉了Flex布局后都不会陌生,这里不多做解释,直接看例子,以align-items 为例:

.container{  display:grid;  grid-template:     "header header" 160px    "footer footer" 160px    / 160px 160px;    height:500px;  grid-row-gap:10px;  grid-column-gap: 10px;}

首先定义四个grid单元,每个单元的长宽均为160px

接下来我们更改align-items的值

align-items:stretch

clipboard.png

align-items:center

clipboard.png

align-items:start

clipboard.png

align-items: end

clipboard.png

为了方便大家理解,我用红框框出每个Grid单元所占用的空间。由此可以看出,place-items属性是用来表明一个元素在当前grid单元中的分布方式,这个元素的拉伸,居中等都是以grid单元作为参考的。

place-content

place-content同样是一个简写属性,它包括:justify-content 和 align-content,它表示grid元素在grid容器中的分布方式,只有当grid容器中有剩余空间的时候才起作用。

语法如下:

justify-content: stretch | start | end | center | space-between | space-around | space-evenly;align-content: stretch | start | end | center | space-between | space-around | space-evenly;

属性值得含义同Flex;这里不再过多说明,读者可以自行验证。

grid-auto-rows 与 grid-auto-columns

grid-auto-rows 和 grid-auto-columns;用于当实际的Grid的元素多余划分的Grid元素时,定义多余Grid元素的长宽;

例如我们在HTML里面一定了五个Grid元素,但是在css中只定义了2*2的Grid单元,可以使用grid-auto来定义多出来的轨道的尺寸。

grid-auto-flow

grid-auto-flow的用法需要结合下面的元素属性来说明。

元素属性

grid-column-start grid-column-end

两个属性是用来定义Grid元素列方向上的起始与终止位置。

语法格式为:

grid-column-start: 
|
| span
| span
| auto

其中:

number为起止第几条网格线
name 为网格线的名称
span <number>网格元素会跨越网格单元的数量
span <name> 当前的网格元素会在哪一个网格线上开始or终止

注意 使用span 如果是start,表示这个从开始的位置跨过的grid单元,如果是end 表示这个元素覆盖的grid单元。

grid-column是它们的简写方式,语法为:

grid-column:grid-column-start / grid-column-end

grid-row-start grid-row-end

grid-row属性与grid-column用法一致,这里不过多赘言,直接看例子:

.container{  display:grid;  grid-template-rows:[rone]1fr[rtwo]3fr[rthree]1fr[rfour];  grid-template-columns: [cone]1fr[ctwo]5fr[cthree]2fr[cfour];  height:500px;}.item:first-child{  grid-column-start:1;  grid-column-end:cfour;  grid-row-start:rone;  grid-row-end: 2;  }.item:nth-child(2){    grid-column-start:1;  grid-column-end:span 1;  grid-row-start:rtwo;  grid-row-end: span cthree;}.item:nth-child(3){    grid-column-start: ctwo;  grid-column-end:4;  grid-row-start:rtwo;  grid-row-end: span cthree;} .item:nth-child(4){  grid-column-start:1;  grid-column-end:4;  grid-row-start:3;  grid-row-end: span 4;}

效果:

clipboard.png

首先在Grid容器中划分出9个grid单元,这九个单元被六个网格线所分割,并给这六个网格线命名。在四个Grid元素中定义横行的起始位置。
grid-row 与 grid-column结合使用,可以起到与Grid-template-areas同样的效果。

grid-area

grid-area我们在前面已经接触过一部分了,他与Grid容器中的grid-template-areas一起定义,也是grid-column与grid-row的简写属性,语法为:

grid-area: 
|
/
/
/
;

name为grid区域的名称,与grid-tempalte-areas结合使用。

上面我们的例子就可以用grid-area表示:

.item:first-child{    grid-area:1/rone/2/cfour;}

place-self

justify-self

justify-self定义Grid元素的水平布局方式的,例如,我们在Grid容器中定义justify-items的属性为默认属性,而在某一个Grid元素中定义justify-self为center,那么其他元素表现为拉伸,这个元素则单独表现为居中。也就是说,justify-self在Grid容器中对应的属性是justify-items。

语法为:

.item {    justify-self: stretch | start | end | center;}

algin-self

align-self与justify-self一致,改变的是这个元素的垂直部署方式,与容器中align-items对应,

语法为:

.container {    align-self: stretch | start | end | center;}

由于这四个属性值已经在我们的系列文章中出现多次,这里不再多说。

plac-self是以上两个属性的简写方式,语法为:

.container {    place-items: 
/
;}

再论fr

Grid的所有属性已经介绍完毕了,在对Grid宇宙有了一个基本的认识后,我们再回头看一下Grid宇宙中出现的新尺寸单位——fr。

可能大家在刚刚结仇到fr这个单位时,都会认为它是%的一个别名;但是,我们来看最下面的例子:
我们在Grid容器中划分出四个Grid区域,并定义每个区域的宽度为25%,并定义每个Grid元素之间的gap宽70px;

.container{  display:grid;  grid-template-columns: repeat(4, 25%);  grid-column-gap: 70px;}

效果如下:

clipboard.png
很明显,这里元素溢出了。这种情况是我们不想看到的。
下面,我们将25%替换为1fr看一下效果:

clipboard.png

效果对比很明显。
而造成两者显著区别的原因是二者的计算空间方式的不同。使用百分比它的分母是父元素的width或者height,而fr的分母是父元素中剩余空间的尺寸;css会首先计算使用%和px定义的元素尺寸,剩下的空间再由fr元素进行比例分配。这就是使用fr不会出现元素溢出的情况。当然我们也可以使用calc避免溢出的尴尬,但是两种解决方案孰优孰略已经一目了然了。

Flex 与 Grid

Flex布局与Grid布局有很多相似的地方,例如justify-content和justify-items的用法。但是更多的是不同,最重要的是Grid开拓了二维布局的方式,相比于传统的css布局方式(Flex、bootstrp 12列),Grid开创了网格的概念,用户可以从横纵两个方面部署元素。正是因为如此,在Grid宇宙中,传统的css布局、尺寸属性就显得格格不入了。而Grid布局的二维特性所带来的整体观,使Grid在页面级别样式上更加游刃有余。而Flex相比于Grid 更加适合小组件上的样式开发,二者并不冲突相信在Grid 与 Flex双双加持之下,一定会收获更好的开发效果!

Grid布局还是一个较新潮的概念,我也是一般看资料学习,一边分享,由于缺少实际的开发经验,对于很多属性的应用场景还没有很深入的理解,故而有的属性一笔带过;如果我有理解不正确的地方,欢迎大家指正!

参考文献

What's more:

转载地址:https://blog.csdn.net/weixin_34248258/article/details/88610429 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:枚举的使用示例
下一篇:vue+node全栈移动商城【8】-vant新建注册页面

发表评论

最新留言

网站不错 人气很旺了 加油
[***.192.178.218]2024年04月18日 01时05分14秒