JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)
前言
春节假期有幸拜读了张鑫旭大大的关于Flex与Grid的两篇文章(见参考文献),很有收获;自己在开发的过程中,很多时候都会采用Flex布局,而Float与inline-box这种方式已经很少使用了;这次在春假期间学习了Grid,深感Grid的好用与便利。趁着这次机会总结一下Grid与Flex的使用。
浏览器支持
- Flex 浏览器支持情况
- Grid浏览器支持情况
可以看出来,相对于Grid来说,Flex无论实在PC端还是移动端都得到了很好的支持,而Grid,在移动端的支持还是差强人意。
FlexBox
在flex布局中,有两个概念需要谨记:容器与元素。在一个html标签中声明样式:display:flex
ordisplay:inline-flex
即声明了一个flex的容器,在这个容器里面的元素即为flex元素。而flex所有的样式属性分为两类:容器属性
与元素属性
,他们均作用于flex元素
,只不过flex容器
中声明的属性统领flex所有元素
整体显示与排布方式,而flex元素
的属性表示单一元素
的排布方式。
下面,根据上面脑图的思路,依次介绍flex的属性。声明:
下面师范的所有元素都遵从以下HTML结构 和基本样式
<style> .container{ height:200px; background-color:#999; } .container >.item{ background-color:#456; width:80px; font-size:30px; color:white; text-align:center; } </style> <div class="container"> <div class="item">1</div> <div class="item">2</div> <div class="item">3</div> <div class="item">4</div> ... </div>
容器属性
flex-direction
flex-direction顾名思义,是控制flex元素的整体布局方向
的,它包括四个属性:
1.row //从左到右 默认 2.row-reverse //从右到左 3.column //从上到下 4.column-reverse //从下到上
1、flex-direction:row
2.flex-direction:row-reverse
3.flex-direction:column
4.flex-direction: column-reverse
上面四个图是分别在容器上(.container)设置flex-direction四个属性得到的效果。
flex-wrap
flex-wrap是控制元素是换行显示还是单行显示,它共有三个属性
1.no-wrap //不换行 默认 2.wrap // 换行 3.wrap-reverse //换行反序
为了更加明显的看出区别,我特别添加了一个难看的边框。
在容器属性上添加flex-wrap,分别设置三个wrap属性
1.flex-wrap: no-wrap
2.flex-wrap: wrap
3.flex-wrap: wrap-reverse
在这里需要注意no-wrap属性:
如果容器元素设置了最小宽度,而且元素的最小宽度之和>父容器的宽度,则显示内容溢出。
如果容器元素没有设置最小宽度或者最小宽度之和<父容器的宽度,则容器元素收缩并将父元素填满,在上面no-wrap例子中,就没有设置子元素的最小宽度,读者可以自行添加验证。
设置wrap-reverse属性后,我们可以看到它的换行结果与wrap的换行结果在行
这一维度上是相反的。
读者可以试试将flex-direction
设置为column
或者其他非默认值,再查看在不同的flex-wrap值下的显示,会有不同的结果哟。
flex-flow
flex-flow是 flex-direction与flex-wrap的统写,语法是flex-flow:<‘flex-direction’> || <‘flex-wrap’>
justify-content
justify-content控制flex元素水平方向的对齐方式,它共有 个属性:
1.flex-start // 默认值 默认情况下左对齐
2.flex-end // 右对齐
3.center // 居中
下面以space开头的属性都是描述剩余空间
的排布方式的
4.space-around //剩余空间围绕在每个
子元素的周围
5.space-between //剩余空间只分布在子元素之间
,两端元素左右没有剩余空间
6.space-evenly // 剩余空间均匀
分布在元素两端、之间
下面看例子:
1.flex-start
2.flex-end
3.center
4.space-between
5.space-around
6.space-evenly
为了更加明显的看出不同space下的额外空间分布特点,我使用红框框出每一属性下的剩余元素。几个属性分布不同不言而喻了。
align-content
align-content与justify-content对应,代表元素垂直方向上的分布。而这种分布方式只有在多行
的情况下才能够凸显出来,单行情况下设置此属性无效。
相对于justify-content,它多出来一个stretch的属性,代表拉伸,默认属性。
1.stretch
2.flex-start
3.flex-end
4.space-between
5.space-around
6.space-evenly
可以看出,它的排布方式与justify-content的逻辑是一致的,只不过方向不同而已。
align-items
既然有了多行情况下控制元素排布方式,就会有单行情况下元素排布方式。align-items就是在单行情况下,控制元素排布方式的。共有5个属性:
1.stretch 默认属性,会将元素的高度拉伸至父容器的高度
2.flex-start 顶部对齐
3.flex-end 底部对齐
4.baseline 基线对齐
5.center 居中
注意:
以上所有的例子展示都是在其他属性默认情况的显示情况,如果更改其他属性(如:flex-direction
与 flex-wrap
)值,会有不同的显示效果。
元素属性
order
order属性可以控制flex元素的排布顺序,flex元素会根据order从小到大依次排布,order的默认值为0,因此如果想要某个元素排在前面,只需要将他的order值设为比0小的值即可。
flex-grow
flex-grow控制元素所占宽度,默认值为0,当容器内有剩余空间时,flex-grow不为0的元素将会按照以下规则扩展:
- 容器中只有一个元素设置了flex-grow
1、flex-grow 值>=1 那么这个元素会填充容器的剩余空间
.container .item:first-child{ order:2; flex-grow:1; }
2、flex-grow 在0-1之间,那么这个元素会多占用空间为剩余空间乘以这个flex-grow的值。
.container .item:first-child{ order:2; flex-grow:0.5; }
.container{ display:flex; justify-content:space-around;//如果子元素的flex-grow<1,此属性依然有效 } .container .item:first-child{ order:2; flex-grow:0.5; }
- 容器中有多个元素设置了flex-grow
1、所有元素的flex-grow的值之和>1
则占用全部的剩余空间,多占用的剩余空间比例即为各个元素所设置flex-grow的比例。
2、所有元素的flex-grow的值之和<1
所占用的剩余空间的比例即为各个元素的felx-grow的值的比例。
flex-shrink
flex-shrink的属性与flex-grow相反,指的是当空间不足的时候,元素的收缩比例,默认值为1;其核心思路与grow一致,这里不再赘述,读者可以自行检验。
flex-basis
flex-basis定义了在分配剩余空间之前,每个元素的默认宽度,默认为auto即元素的宽度;当flex-basis的值不为auto时,其显示的优先级是高于元素的width的。
flex
flex属性为以上三个属性的统称,语法为:flex: none | auto | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
flex翻译为中文就是弹性的,所以这个属性就是说明当有空间过大or空间不足时,每个元素如何分布。
align-self
align-self顾名思义,就是确定单个元素垂直分布状态;其在父容器对应的属性是algin-items;
其属性值有align-items一致,只不过多了一个auto默认属性,表示与父元素的auto-items值一致。
来看例子:
对应css代码:
.container{ display:flex; align-items:center; } .container .item:nth-child(2n+1){ order:2; flex-grow:2; align-self:flex-start; }
我在父元素上添加align-items属性,使flex元素居中对齐,在子元素上添加align-self属性,使奇数子元素向上对齐。
当有多行的情况下,但是align-content未设置,我们可以看到,每一个设置了align-self属性的子元素会在当前的行按照align-self属性显示,但是当align-content属性设置后,其align-self属性失效(见下图)。
对应代码:
.container{ display:flex; align-content:center; flex-wrap:wrap; } .container .item:nth-child(2n+1){ order:2; flex-grow:2; align-self:flex-start; }
总结
flex布局就总结到这里,里面有些类似属性没有举例子,还需要读者自己去验证。相对于其他解决方案,flex布局更加简洁,也更加具有语义性;最显而易见的,可以很方便的解决我们平时面试过程中遇到的多栏布局,垂直居中问题。
其实细细品读flex,相比于Grid而言,他还是更加线性化,就是把所有的元素都看成一条线,确定这条线的方向、居中垂直方式,当这条线超过父元素的范围,我们怎样处理。所以,虽然flex看似有许多属性,但是合理的理解后,还是非常简单的。
这篇是glex与Grid的上篇,主要介绍了flex,而Grid的相关属性与应用,我们下篇见。