当前位置: 首页 > Web前端 > CSS

JavaScript五十问-CSSGrid与FlexBox的比较(下)

时间:2023-03-30 14:26:38 CSS

前言在第一部分-JavaScript五十问-CSSGrid与FlexBox的比较(上),我介绍了Flex的属性和使用,今天我们会总结一下Grid的具体用法,最后说一下Flex和Grid布局的联系和区别。需要注意的是,网格布局与我们之前熟悉的css布局思路有很大的不同。在阅读本文之前,我们需要摒弃平时对css的刻板印象,准备好接受知识的洗礼吧,少年!Grid和Flex一样,Grid也分为容器和元素两个概念;在一个html标签中添加一个样式:display:grid或者display:inline-grid,即构建一个Grid容器,里面的dom元素就是Grid元素。同样,Grid也分为两类属性,分别加载在容器和元素上,下面会一一说明。HTML结构说明以下所有示例均基于或扩展以下HTML结构:1

2
3
4
5Grid基本概念介绍GridGrid容器有一系列grids的概念;听起来很可怕,但组合图很容易理解。网格线水平方向和垂直方向的线段为网格线。网格轨道的两条相邻平行网格线之间的区域为网格轨道。由网格单元的四个相邻边组成的区域为网格单元。.frfr是Grid中特有的大小单位,是fraction-fraction的缩写。假设我们现在有四个网格元素,每个元素的宽度是1fr,那么每个元素的实际宽度是总宽度的1/4。fr也可以和%、px一起使用,它的计算规则是去掉px和%的剩余空间作为fr分配空间,所有fr的和作为分母,分子为fr对应的值每个元素。(当然,在Grid上下文中,我们不需要设置width属性,这个给大家理解)。这样看来,fr只是%的另一种写法。通过我的介绍,你会发现fr优于%。接下来我会结合脑图的思想来介绍Grid的各种属性。容器属性grid-templategrid-tempalte是三个属性的简写,是描述整个区域的属性,即多个网格单元。grid-template-rowsgrid-template-rows描述了水平单元轨道属性。试想一下,我们在一个Grid容器中,我们关心这个属性干什么?无非就是这个容器里有多少行,每行的高度;因此,这个属性是为我们定义这些值的。我们先看语法:grid-template-rows:|<行名><轨道大小>...;此属性允许我们定义两个轨道大小和编号以及轨道之间的网格线的名称。至于它的作用,先不一一列举。首先,让我们看看这个属性是如何定义每个轨道的大小和轨道数量的。我们先来看一个例子:.container{grid-template-rows:200pxauto1fr1fr20%;grid-row-gap:10px;//定义轨道之间的间距}grid-template-rows定义了五个值,表示Grid容器中有五行,可以使用任意方式定义大小。效果如下。auto值表示元素实际占用的大小。网格分配空间先计算出fr对应的轨道大小,然后将剩余的大小按比例分配给fr加持的元素。上面,我们在Grid容器中定义了五行容器轨道。当我们定义太多曲目时,我们可以使用重复功能来减少我们的工作量。语法为:grid-template-rows:repeat(n,size)示例:.container{grid-template-rows:repeat(5,1fr);grid-row-gap:10px;}上面定义了五个网格轨道,每个轨道的高度为Grid容器高度的1/5。grid-template-columnsgrid-template-columns和grid-template-rows的使用方式相同。这两个属性共同作用在Grid容器上,相当于把Grid容器分成了m*n个子区域。示例:.container{网格模板行:重复(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表示gridarea.表示一个空的网格区域none表示没有定义网格区域。我们平时开发的时候,经常会有这样的布局,上下两列居中。接下来我们使用grid-template-areas来完成这样的布局。<样式>.container{显示:网格;网格模板行:60px自动60px;网格模板列:100px1fr;grid-template-areas:"headerheader""leftright""footerfooter";}.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{显示:网格;网格模板行:60px1fr60px;网格模板列:100px1fr;grid-template-areas:"headerheader""leftright""footerfooter";}.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;网格模板行:60px1fr60px;网格模板列:100px1fr;grid-template-areas:"headerheader""leftright""footerfooter";}.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;}1234在Grid容器中,我们定义了6个网格单元使用grid-tempalte-areas将页眉页脚左右划分为四个区域;而在grid元素中,每个元素都使用grid-area来指定该元素对应的网格区域。因此,虽然我们划分了6个单元,但是可以用四个元素来表示。是不是很神奇?更神奇的是grid-area-name支持中文定义。以上grid-template的子属性就完成了。grid-template是以上三个属性的缩写。语法如下:grid-tempalte:<'grid-template-rows'>/<'grid-template-columns'>``grid-tempalte:[?<字符串><轨道大小>?<线名>?]+[/]?比如上面的例子可以简写为grid-template:"headerheader"60px"leftright"1fr"footerfooter"60px/50px1fr;grid-gapgrid-gap用于描述Grid区域之间的间隙大小。语法如下:.container{grid-gap:;}grid-gap是一个简写属性,也可以定义网格行间隔和网格列间隔分别。.container{grid-row-gap:10px;grid-column-gap:10px;}grid-gap与margin和padding不同,它不占据当前元素的盒模型的位置。上图清楚地表明元素3的margin和padding都是零。place-itemsplace-items是justify-items和align-items的简写。这两个属性分别定义了Grid元素的水平和垂直分布。语法如下:justify-items:stretch|开始|结束|中心;对齐项目:拉伸|不多解释,直接看例子,以align-items为例:.container{display:grid;grid-template:"headerheader"160px"footerfooter"160px/160px160px;高度:500px;网格行间距:10px;grid-column-gap:10px;}首先定义四个网格单元,每个单元的长宽都是160px接下来,我们改变align-itemsalign-items:stretchalign-items:centeralign-items:startalign-items的值:end为了方便大家理解,我用红框框出每个Grid单元所占的空间。由此可见,place-items属性是用来表示一个元素在当前网格单元中的分布情况。这个元素的拉伸和居中都是以网格为单位的。place-contentplace-content也是一个简写属性,包括:justify-content和align-content,表示网格元素在网格容器中的分布,只有在网格容器有剩余空间时才起作用。语法如下:justify-content:stretch|开始|结束|中心|间隔|环绕空间|空间均匀;对齐内容:拉伸|开始|结束|中心|间隔|环绕空间|;属性值的含义与Flex相同;此处无需过多解释,读者可自行验证。网格自动行和网格自动列网格自动行和网格自动列;当实际Grid元素与分割的Grid元素冗余时,用于定义冗余Grid元素的长度和宽度;比如我们在HTML中指定了5个Grid元素,但是css中只定义了2*2个Grid单元,可以使用grid-auto来定义多出来的track的大小。grid-auto-flowgrid-auto-flow的使用需要结合以下元素属性进行说明。元素属性grid-column-startgrid-column-end两个属性用来定义Grid元素列方向的开始和结束位置。语法格式为:grid-column-start:|<名称>|跨度<数字>|跨度<名称>|auto其中:number是第一条和最后一条网格线name是网格线的名称span网格元素将跨越网格单元的数量span当前网格元素将在哪条网格线上开始或结束注意span的使用如果是start,表示从起始位置开始跨越的网格单元,如果是end,表示该元素覆盖的网格单元。grid-column是他们的缩写,语法是:grid-column:grid-column-start/grid-column-endgrid-row-startgrid-row-endgrid-row属性和grid-column用法一致,不过这里也是话不多说,直接看例子:.container{display:grid;网格模板行:[rone]1fr[rtwo]3fr[rthree]1fr[rfour];网格模板列:[cone]1fr[ctwo]5fr[cthree]2fr[cfour];height:500px;}.item:first-child{grid-column-start:1;网格列端:cfour;网格行开始:rone;网格行尾:2;}.item:nth-child(2){grid-column-start:1;网格列端:跨度1;网格行开始:rtwo;grid-row-end:spancthree;}.item:nth-child(3){grid-column-start:ctwo;网格列端:4;网格行开始:rtwo;grid-row-end:spanctree;}.item:nth-child(4){grid-column-start:1;网格列端:4;网格行开始:3;grid-row-end:span4;}作用:先在Grid容器中划分9个网格单元,将这9个单元格划分为6条网格线,并为6条网格线命名。在四个Grid元素中定义行的起始位置。Grid-row与grid-column结合使用,具有与Grid-template-areas相同的效果。grid-areagrid-area我们之前已经接触过一部分了。它与grid-template-areas一起定义在Grid容器中,也是grid-column和grid-row的简写属性。语法是:grid-area:|///;name为网格区域名称,与grid-tempalte-areas结合使用。我们上面的例子可以用grid-area表示:.item:first-child{grid-area:1/rone/2/cfour;}place-selfjustify-selfjustify-self定义了Grid元素的水平布局,例如,我们在Grid容器中定义justify-items属性为默认属性,在某个Grid元素中定义justify-self为center,则其他元素会被拉伸,而这个元素会单独居中。也就是说Grid容器中justify-self对应的属性是justify-items。语法是:.item{justify-self:stretch|开始|结束|center;}algin-selfalign-self和justify-self一致,变化的是这个元素的垂直部署,对应容器中的align-items,语法为:.container{align-self:stretch|开始|结束|center;}由于这四个属性值在我们的系列文章中多次出现,这里就不多说了。plac-self是以上两个属性的缩写,语法为:.container{place-items:/;}此外,frGrid的所有属性都已经介绍过了,在Griduniverse有了基本的了解之后,我们再回头看看Griduniverse中出现的新的尺寸单位——fr。可能刚接触到fr这个单位,你会认为它是%的别名;但是,我们看下面的例子:我们在Grid容器中划分了四个Grid区域,并定义每个区域的宽度为25%,并定义每个Grid元素之间的间隙宽度为70px;.container{显示:网格;网格模板列:重复(4、25%);grid-column-gap:70px;}效果如下:很明显,元素在这里溢出了。这种情况是我们不愿意看到的。接下来我们把25%换成1fr看看效果:效果对比很明显。两者之所以有显着差异,是因为它们计算空间的方式不同。使用百分比,它的分母是父元素的宽度或高度,而fr的分母是父元素中剩余空间的大小;css会先计算%和px定义的元素大小,剩余空间由fr元素按比例分配。这是使用fr时发生的情况,没有元素溢出。当然我们也可以使用calc来避免溢出的尴尬,但是两种方案哪个更好一目了然。Flex和GridFlex布局和Grid布局有很多相似之处,比如justify-content和justify-items的使用。但是还有更多的不同。最重要的是Grid开发了二维布局方式。相对于传统的CSS布局方式(Flex、bootstrp12列),Grid开创了网格的概念。方面部署元素。正因为如此,在Grid宇宙中,传统的css布局和大小属性格格不入。Grid布局的二维性带来的整体视图,让Grid在页面级风格中更加得心应手。与Grid相比,Flex更适合小组件上的样式开发。两者并不冲突。相信在Grid和Flex的共同支持下,会取得更好的开发效果!网格布局仍然是一个相对较新的概念。我平时看资料边学习边分享。由于缺乏实际开发经验,对很多属性的应用场景了解不深,所以部分属性就一笔带过;如有不明白的地方,欢迎指正!参考资料MDN:GridLayout张新旭:给自己展示一下:gridlayouttutorial知乎:CSS新长度单位fr你知道吗?补充:JavaScript五十问——CSSGrid与FlexBox对比(上)