资讯专栏INFORMATION COLUMN

JavaScript五十问——对比来说CSS的Grid与FlexBox(下篇)

Moxmi / 1393人阅读

摘要:语法如下是简写属性,也可以分别定义行间隔和列间隔。语法如下属性值得含义同这里不再过多说明,读者可以自行验证。

前言

在上篇——JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇),我介绍了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容器里面有网格一系列的概念;听着唬人,但是结合图很容易理解。

网格线

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

网格轨道

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

网格单元

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

fr

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

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

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


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

容器属性 grid-template

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

grid-template-rows

grid-template-rows是描述横向单元轨道属性的。可以试想一下,我们在一个Grid容器中,关于这个属性,我们关心的是什么呢?无非就是这个容器中有多少行,每行的高度;所以,这个属性就是让我们定义这些值得。先来看语法:
grid-template-rows: | ...;
这个属性除了可以定义轨道尺寸和个数之外,还允许我们定义两个轨道之间的网格线的名称,至于他的作用,我们先按下不表,先来看这个属性是怎样定义每个轨道的尺寸和轨道个数的。
先来看一个例子:

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

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

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

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


上面就定义了五个网格轨道,每个轨道的高度是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个单元,但可以使用四个元素来表示。

是不是很神奇呢,更神奇的是,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不同,它不占用当前元素的盒模型的位置。


上图显示的很清楚,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

align-items:center

align-items:start

align-items: end


为了方便大家理解,我用红框框出每个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 网格元素会跨越网格单元的数量
span 当前的网格元素会在哪一个网格线上开始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;
} 

效果:


首先在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;
}

效果如下:

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


效果对比很明显。
而造成两者显著区别的原因是二者的计算空间方式的不同。使用百分比它的分母是父元素的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布局还是一个较新潮的概念,我也是一般看资料学习,一边分享,由于缺少实际的开发经验,对于很多属性的应用场景还没有很深入的理解,故而有的属性一笔带过;如果我有理解不正确的地方,欢迎大家指正!

参考文献

MDN:Grid Layout
张鑫旭:写给自己看的display: grid布局教程
知乎:CSS 新的长度单位 fr 你知道么?

What"s more:

JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/117410.html

相关文章

  • JavaScript十问——对比来说CSSGridFlexBox(上篇)

    摘要:前言春节假期有幸拜读了张鑫旭大大的关于与的两篇文章见参考文献,很有收获自己在开发的过程中,很多时候都会采用布局,而与这种方式已经很少使用了这次在春假期间学习了,深感的好用与便利。相对于,它多出来一个的属性,代表拉伸默认属性。 前言 春节假期有幸拜读了张鑫旭大大的关于Flex与Grid的两篇文章(见参考文献),很有收获;自己在开发的过程中,很多时候都会采用Flex布局,而Float与in...

    xuhong 评论0 收藏0
  • JavaScript 十问——认真聊一聊去抖节流

    摘要:前言无论是面试还是在讨论浏览器优化过程中,都会涉及到去抖动和节流的问题。总的来说,这二者是一种限制事件触发频率的方式。不同的是,节流会指定事件触发的时间间隔而去抖动会指定事件不触发的时间间隔。 前言 无论是面试还是在讨论浏览器优化过程中,都会涉及到去抖动和节流的问题。总的来说,这二者是一种限制事件触发频率的方式。不同的是,节流会指定事件触发的时间间隔;而去抖动会指定事件不触发的时间间隔...

    chadLi 评论0 收藏0
  • JavaScript 十问——认真聊一聊去抖节流

    摘要:前言无论是面试还是在讨论浏览器优化过程中,都会涉及到去抖动和节流的问题。总的来说,这二者是一种限制事件触发频率的方式。不同的是,节流会指定事件触发的时间间隔而去抖动会指定事件不触发的时间间隔。 前言 无论是面试还是在讨论浏览器优化过程中,都会涉及到去抖动和节流的问题。总的来说,这二者是一种限制事件触发频率的方式。不同的是,节流会指定事件触发的时间间隔;而去抖动会指定事件不触发的时间间隔...

    EscapedDog 评论0 收藏0
  • Javascript十问——从源头细说WebpackGulp

    摘要:前言与是目前圈子内比较活跃的前端构建工具。对于初学者来说,对这二者往往容易认识不清,今天,就从事件的源头,说清楚与。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。打包后形成的文件出口。 前言:Webpack 与 gulp是目前圈子内比较活跃的前端构建工具。网上有很多二者比较的文章,面试中也会经常遇到gulp,Webpack的区别这样的问题。对于初学者来说,对这二...

    lwx12525 评论0 收藏0
  • Javascript 十问——实现继承多种方式

    摘要:组合继承实现了属性分离,方法共享下的完美继承方案继承我们的主角,,就是对组合继承的改进。这也是为什么在子类构造函数中一定要显示调用的原因。 谈到继承,或者更广义上的:一个对象可以使用另外一个对象的属性或方法。实现起来无外乎有两种方式:apply or call 改变this的作用域原型继承 改变__proto__指向,添加作用域链 而JavaScript所有的继承实现,都是围绕以上两点...

    BlackHole1 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<