当前位置: 首页 > 科技观察

flexbox布局的正确使用姿势

时间:2023-03-14 23:42:56 科技观察

在项目中,我们也会用到很多flexbox的新旧属性,但一般人一般只写新属性,旧属性由autoprefixer处理,但实际上,执行相同功能的新旧属性的表现形式是不一样的。也有一些人只使用“通用”的flex:number属性来为灵活的项分配空间,但有些特殊场景无法满足。本文梳理了新旧flexbox属性的区别和空间分配原则,为大家使用flexbox布局。项目一路走来。FlexboxCompatibilityPCCompatibilityMobileCompatibility如上所示,为了兼容IE10-11和Android4.3-,UC,我们还是要用到Flexbox的老属性。Flexbox的新旧属性Flexbox的新属性提供了很多旧版本没有的功能,但是目前Android4.可以实现相同功能的Flexbox的新旧属性如下:但想象是美好的,现实却是残酷的。新老楼都有几个顽固分子不能乖乖乖乖的表现一样,总有那么一点差别。让我们看一下新旧属性有哪些不同:flex-direction:row-reversevsbox-orient:horizo??ntal;box-direction:reverse同理:改变主轴的方向和flexitem的顺序;从右到左排列的ltr下的弹性项目。区别:flex-direction:row-reverse:第一个弹性项对齐到主轴的起点box-orient:horizo??ntal;box-direction:reverse:最后一个flexibleitem对齐到主轴的末端flex-direction:column-reversevsbox-orient:vertical;box-direction:reverse相同点:改变主轴的方向和灵活项目的排列顺序;在ltr下,灵活的项目是从下到上排列的。不同点:flex-direction:column-reverse:第一个弹性项对齐到主轴的起点。box-orient:vertical;box-direction:reverse:最后一个灵活的项目与主轴的末端对齐。oreder:integervsbox-ordinal-group:integer相同点:定义灵活项的显示顺序。区别:order:integer:默认值为0;它可以是负的。box-ordinal-group:integer:默认值为1;该值大于1。flex-grow:numbervsbox-flex:number相同点:定义flexitem的扩展系数。区别:box-flex:number还定义了flexitem的收缩系数。flex-shrink:numbervsbox-flex:number相同点:定义flexitem的收缩系数。不同点:box-flex:number还定义了flexitem的扩展因子。Flexbox分配空间的原则影响Flexbox布局分配空间的属性有3个,分别是flex-grow、flex-shrink和flex-basis。flex-grow:当柔性项在主轴方向的总宽度时flex-shrink:当柔性项在主轴方向的总宽度>柔性容器时,柔性项分配总宽度超过的空间根据收缩系数的柔性容器。flex-basis:拉伸的基础。在计算剩余空间或超出空间之前,重新设置flexitem的宽度,然后再计算。我们先来看看如何计算被拉伸物品拉伸后的宽度。先给出一个简单明了的公式,然后通过举个栗子来验证一下。flexibleitem展开宽度=(itemcontainerwidth-itemwidthoritem设置的flex-basis之和)*对应的flex-growratio展开后的itemwidth=原来的flexibleitemwidth+expandedwidth.flexbox-wrap{width:550px;display:flex;}.flexbox-item{&:nth-child(1){width:60px;}&:nth-child(2){width:70px;}&:nth-child(3){flex-basis:80px;}&:nth-child(4){flex-basis:90px;}&:nth-child(5){flex-basis:100px;}}@for$ifrom1through5{.flexbox-item:nth-child(#{$i}){flex-grow:$i;background-color:rgba(35*(6-$i),20*$i,35*$i,1);}}让我们计算拉伸上面栗子中第一个弹性项的宽度。按照公式一步步计算://Itemcontainerwidthcontainer=550//itemwidthoritemsettingflex-basisitemSum=60+70+80+90+100=400//对应的flexfirstflexibleitem-growratioflexRatio=1/(1+2+3+4+5)=1/15//第一个伸缩项的展开宽度extendWidth=(550-400)*1/15=10//第一个拉伸项的拉伸宽度itemWidth=60+10=70经过计算,第一个拉伸项的拉伸宽度为70px。我们用chrome上的盒子模型看看是否正确。chrome的计算结果和我们的计算结果是一致的。是否容易根据拉伸的计算公式推导出压缩的计算公式?拉伸项缩小后的宽度=(项设置的项宽度或flex-basis的总和-项容器的宽度)*压缩后对应的flex-shrink比率弹性项宽度=原始弹性项宽度-缩小宽度,继续用栗子验证公式是否正确。flexbox-wrap{width:250px;display:flex;}.flexbox-item{&:nth-child(1){width:60px;}&:nth-child(2){width:70px;}&:nth-child(3){flex-basis:80px;}&:nth-child(4){flex-basis:90px;}&:nth-child(5){flex-basis:100px;}}@for$ifrom1through5{.flexbox-item:nth-child(#{$i}){flex-shrink:$i;background-color:rgba(35*(6-$i),20*$i,35*$i,1);}}我们来计算一下上面栗子中第一个灵活项的压缩宽度。按照公式一步步计算://Itemcontainerwidthcontainer=250//itemwidthoritemsettingflex-basisitemSum=60+70+80+90+100=400//对应的flexfirstflexibleitem-shrinkratioflexRatio=1/(1+2+3+4+5)=1/15//第一个伸缩item收缩宽度extendWidth=(400-250)*1/15=10//第一个伸缩项目项目的压缩宽度itemWidth=60-10=50经过计算,第一个伸缩项目的压缩宽度为50px。我们用chrome上的盒子模型看看是否正确。chrome的计算结果和我们的计算结果不一样。.flexitem压缩的计算方式和拉伸是不一样的,因为会出现压缩的极端情况。我们把第一个flexitem的flex-shrink改成10,缩小后的宽度为(400-250)*(10/24)=62.5,缩小后的宽度比原来的宽度大,计算出来的压缩宽度就变成了负数。为了避免这种极端情况,收缩率的计算考虑了弹性项目的原始宽度。正确的公式是flexibleitem缩小后的宽度=(itemwidth或item设置的flex-basis之和-itemcontainer的宽度)(对应的flex-shrinkitemwidth或flex-basisitem设置的比例)压缩后的item宽度=原来的flexibleitem宽度-缩小后的width对应分步计算公式://itemcontainerwidthcontainer=250//itemwidthorflex-basissumofitemsettingsitemSum=60+70+80+90+100=400//th伸缩比例flexRatio=(1*60)/(1*60+2*70+3*80+4*90+5*100)=6/130//第一个flexibleitem对应一个flexibleitem减少宽度extendWidth=(400-250)*6/130≈6.922//第一个flexibleitem的压缩宽度itemWidth=60-6.922=53.078后计算出来,第一个flexibleitem的压缩宽度是53.078px,和chrome上的boxmodel是一样的。Flexbox属性缩写陷阱上面介绍的flex-grow、flex-shrink和flex-basis都有缩写的写法flex。flex:flex-grow[flex-shrink][flex-basis]flex的各种缩写值flex:initial==flex:01autoflex:none==flex:00autoflex:auto==flex:11autoflex:number==flex:number10%实际项目中会直接写缩写flex为灵活项分配空间,但是使用abbreviated属性会留下一些陷阱,导致性能不理想。分别使用flex和flex-grow来拉伸柔性项来填充容器,看看性能上的差异。先看使用flex-grow.flexbox-wrap{width:550px;display:flex;}.flexbox-item{flex-grow:1;&:nth-child(1){width:60px;}&:nth-child(2){width:70px;}&:nth-child(3){width:80px;}&:nth-child(4){width:90px;}&:nth-child(5){width:100px;}}@for$ifrom1through5{.flexbox-item:nth-child(#{$i}){background-color:rgba(35*(6-$i),20*$i,35*$i,1);}}每个弹性项在原来的宽度上拉伸相同的宽度通过上面计算拉伸后的弹性项宽度,可以计算出第一个弹性项的拉伸宽度//itemcontainerWidthcontainer=550//itemwidthorsumofflex-basisofprojectsettingsitemSum=60+70+80+90+100=400//第一个flexibleitem对应的flex-growratioflexRatio=1/(1+1+1+1+1)=1/5//第一个拉伸项的拉伸宽度extendWidth=(550-400)*1/5=30//第一个拉伸项的拉伸宽度itemWidth=60+30=90然后我们将flex-grow:1替换成flex:1,下面是性能效果,拉伸后物品的宽度变得相同。从chrome的box模型可以看出,flexibleitem拉伸后的宽度变成了110px,flexiblecontainer平分了container的宽度。flex:1展开后就是flex:110%,flex-grow:1相当于flex:11auto。两者的区别在于flex-basis的值。flex:1将item宽度重置为0,所以可分配的空间就是整个容器,从公式计算可以更直观的理解://itemcontainerwidthcontainer=550//itemwidthorflex的总和-basissetbytheitemitemSum=0+0+0+0+0=0//第一个flexibleitem对应的flex-growratioflexRatio=1/(1+1+1+1+1)=1/5//第一个StretchableitemextendedwidthextendWidth=(550-0)*1/5=110//第一个stretchableitem拉伸后的宽度itemWidth=0+110=110需要注意的Flexbox特性无效了属性column-*在可伸缩容器中无效float和clear在弹性项目中无效vertical-align在弹性项目中无效::first-line和::first-letter在弹性容器中无效非空字符文本节点在弹性中container也是flexitems12Iamafaketext345margin折叠flexcontainer和flexitem的margin不会折叠flexitems之间的margin不会折叠B旧版Flexbox的UG。应将Flex项目添加为内联元素display:block;或显示:flex