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

前言

春节假期有幸拜读了张鑫旭大大的关于Flex与Grid的两篇文章(见参考文献),很有收获;自己在开发的过程中,很多时候都会采用Flex布局,而Float与inline-box这种方式已经很少使用了;这次在春假期间学习了Grid,深感Grid的好用与便利。趁着这次机会总结一下Grid与Flex的使用。

浏览器支持

  • Flex 浏览器支持情况

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

  • Grid浏览器支持情况

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

可以看出来,相对于Grid来说,Flex无论实在PC端还是移动端都得到了很好的支持,而Grid,在移动端的支持还是差强人意。

FlexBox

在flex布局中,有两个概念需要谨记:容器与元素。在一个html标签中声明样式:display:flexordisplay:inline-flex即声明了一个flex的容器,在这个容器里面的元素即为flex元素。而flex所有的样式属性分为两类:容器属性元素属性,他们均作用于flex元素,只不过flex容器中声明的属性统领flex所有元素整体显示与排布方式,而flex元素的属性表示单一元素的排布方式。

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

下面,根据上面脑图的思路,依次介绍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
《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》

2.flex-direction:row-reverse
《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》

3.flex-direction:column
《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》
4.flex-direction: column-reverse
《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》

上面四个图是分别在容器上(.container)设置flex-direction四个属性得到的效果。

flex-wrap

flex-wrap是控制元素是换行显示还是单行显示,它共有三个属性

1.no-wrap //不换行 默认
2.wrap // 换行
3.wrap-reverse //换行反序

为了更加明显的看出区别,我特别添加了一个难看的边框。
在容器属性上添加flex-wrap,分别设置三个wrap属性
1.flex-wrap: no-wrap

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

2.flex-wrap: wrap
《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》

3.flex-wrap: wrap-reverse
《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》
在这里需要注意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

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

2.flex-end

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

3.center

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

4.space-between

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

5.space-around

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

6.space-evenly
《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》
为了更加明显的看出不同space下的额外空间分布特点,我使用红框框出每一属性下的剩余元素。几个属性分布不同不言而喻了。

align-content

align-content与justify-content对应,代表元素垂直方向上的分布。而这种分布方式只有在多行的情况下才能够凸显出来,单行情况下设置此属性无效。
相对于justify-content,它多出来一个stretch的属性,代表拉伸,默认属性。

1.stretch

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

2.flex-start

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

3.flex-end

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

4.space-between

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

5.space-around

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

6.space-evenly

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

可以看出,它的排布方式与justify-content的逻辑是一致的,只不过方向不同而已。

align-items

既然有了多行情况下控制元素排布方式,就会有单行情况下元素排布方式。align-items就是在单行情况下,控制元素排布方式的。共有5个属性:
1.stretch 默认属性,会将元素的高度拉伸至父容器的高度

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

2.flex-start 顶部对齐

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

3.flex-end 底部对齐

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

4.baseline 基线对齐

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

5.center 居中

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

注意:以上所有的例子展示都是在其他属性默认情况的显示情况,如果更改其他属性(如:
flex-directionflex-wrap)值,会有不同的显示效果。

元素属性

order

order属性可以控制flex元素的排布顺序,flex元素会根据order从小到大依次排布,order的默认值为0,因此如果想要某个元素排在前面,只需要将他的order值设为比0小的值即可。

flex-grow

flex-grow控制元素所占宽度,默认值为0,当容器内有剩余空间时,flex-grow不为0的元素将会按照以下规则扩展:

  • 容器中只有一个元素设置了flex-grow
    1、flex-grow 值>=1 那么这个元素会填充容器的剩余空间

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

.container .item:first-child{
  order:2;
  flex-grow:1;
}
2、flex-grow 在0-1之间,那么这个元素会多占用空间为剩余空间乘以这个flex-grow的值。

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

.container .item:first-child{
  order:2;
  flex-grow:0.5;
}

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

.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值一致。
来看例子:

《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》
对应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属性,使奇数子元素向上对齐。

《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》
当有多行的情况下,但是align-content未设置,我们可以看到,每一个设置了align-self属性的子元素会在当前的行按照align-self属性显示,但是当align-content属性设置后,其align-self属性失效(见下图)。

《JavaScript五十问——对比来说CSS的Grid与FlexBox(上篇)》
对应代码:

.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的相关属性与应用,我们下篇见。

参考文献

张鑫旭:写给自己看的display: flex布局教程
阮一峰:Flex 布局教程

    原文作者:蔺相如如
    原文地址: https://segmentfault.com/a/1190000018182409
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞