在项目中,咱们还会大量使用到flexbox的新旧属性,但大多数人通常只会写新属性,旧属性交由autoprefixer处理,但其实完成一样功能的新旧属性表现形式却不尽相同。还有部分人只使用“万能”的flex:number属性为伸缩项目分配空间,但有些特殊情景却没法知足,此文为此梳理了flexbox的新旧属性区别和分配空间的原理,为你们用flexbox布局的项目统统渠。chrome
PC端的兼容性segmentfault
移动端的兼容性布局
如上图,为了兼容IE10-11和Android4.3-,UC,咱们仍须要使用Flexbox的旧属性。flex
Flexbox的新属性提供了不少旧版本没有的功能,可是目前Android4.x和UC仍有必定市场占有率须要兼容,所以目前只使用新旧属性都有的功能。
能实现相同功能的Flexbox新旧属性以下表:flexbox
但想象是美好的,现实是残酷的,新旧属性里有那么几个顽固分子并不能乖乖的表现的同样,总有那么一点不一样。
下面咱们来看看是哪些新旧属性有不一样:spa
flex-direction:row-reverse
vs box-orient:horizontal;box-direction:reverse
相同点:改变主轴方向和伸缩项目的排列顺序;在ltr下伸缩项目从右到左排列。
不一样点:3d
flex-direction:row-reverse
:第一个伸缩项目向主轴起点对齐code
box-orient:horizontal;box-direction:reverse
:最后一个伸缩项目向主轴终点对齐blog
flex-direction:column-reverse
vs box-orient:vertical;box-direction:reverse
相同点:改变主轴方向和伸缩项目的排列顺序;在ltr下伸缩项目从下到上排列。
不一样点:flex-direction:column-reverse
:第一个伸缩项目向主轴起点对齐。element
box-orient:vertical;box-direction:reverse
:最后一个伸缩项目向主轴终点对齐。
oreder:integer
vs box-ordinal-group:integer
相同点:定义伸缩项目显示顺序。
不一样点:oreder:integer
:默认值为0;能够为负值。box-ordinal-group:integer
:默认值为1;取值大于1。
flex-grow:number
vs box-flex:number
相同点:定义伸缩项目的扩展因素。
不一样点:box-flex:number
同时定义了伸缩项目的缩小因素。
flex-shrink:number
vs box-flex:number
相同点:定义伸缩项目的缩小因素。
不一样点:box-flex:number
同时定义了伸缩项目的扩展因素。
影响Flexbox布局分配空间的属性有三个,分别是flex-grow
、flex-shrink
和flex-basis
。
flex-grow
:当伸缩项目在主轴方向的总宽度 < 伸缩容器,伸缩项目根据扩展因素分配伸缩容器的剩余空间。
flex-shrink
:当伸缩项目在主轴方向的总宽度 > 伸缩容器,伸缩项目根据缩小因素分配总宽度超出伸缩容器的空间。
flex-basis
:伸缩基础,在进行计算剩余空间或超出空间前,给伸缩项目从新设置一个宽度,而后再计算。
咱们先来看看如何计算计算拉伸后的伸缩项目宽度,先简单明了的给个公式,再经过栗子来验证。
伸缩项目扩展宽度 = (项目容器宽度 - 项目宽度或项目设置的
flex-basis
总和) * 对应的flex-grow
比例拉伸后伸缩项目宽度 = 原伸缩项目宽度 + 扩展宽度
.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 $i from 1 through 5 { .flexbox-item:nth-child(#{$i}){ flex-grow: $i; background-color: rgba(35 * (6-$i), 20 * $i, 35 * $i,1); } }
咱们来计算一下上面栗子中第一个伸缩项目拉伸后的宽度。
对应着公式一步步计算:
// 项目容器宽度 container = 550 // 项目宽度或项目设置的flex-basis总和 itemSum = 60 + 70 + 80 + 90 + 100 = 400 // 第一个伸缩项目对应的flex-grow比例 flexRatio = 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 $i from 1 through 5 { .flexbox-item:nth-child(#{$i}){ flex-shrink: $i; background-color: rgba(35 * (6-$i), 20 * $i, 35 * $i,1); } }
咱们来计算一下上面栗子中第一个伸缩项目压缩后的宽度。
对应着公式一步步计算:
// 项目容器宽度 container = 250 // 项目宽度或项目设置的flex-basis总和 itemSum = 60 + 70 + 80 + 90 + 100 = 400 // 第一个伸缩项目对应的flex-shrink比例 flexRatio = 1 / ( 1 + 2 + 3 + 4 + 5 ) = 1/15 // 第一个伸缩项目缩小宽度 extendWidth = ( 400 - 250 ) * 1/15 = 10 // 第一个伸缩项目压缩后的宽度 itemWidth = 60 - 10 = 50
计算后获得第一个伸缩项目压缩后的宽度是50px,咱们经过chrome上的盒子模型来看看是否正确
chrome计算的结果和咱们计算的结果不同。
伸缩项目压缩的计算方式和拉伸的不同,是由于压缩会有极端状况,咱们把第一个伸缩项目的flex-shrink
修改成10,此时缩小宽度为( 400 - 250 ) * ( 10 / 24) = 62.5
,缩小的宽度比原宽度要大,计算的压缩后的宽度变成了负数。
为了不这种极端状况,计算缩小比例是要考虑伸缩项目的原宽度。
正确的公式是这样的
伸缩项目缩小宽度 = (项目宽度或项目设置的flex-basis总和 - 项目容器宽度) (对应的flex-shrink 项目宽度或项目设置的flex-basis比例)
压缩后伸缩项目宽度 = 原伸缩项目宽度 - 缩小宽度
对应着公式一步步计算:
// 项目容器宽度 container = 250 // 项目宽度或项目设置的flex-basis总和 itemSum = 60 + 70 + 80 + 90 + 100 = 400 // 第一个伸缩项目对应的flex-shrink比例 flexRatio = (1*60) / (1*60+2*70+3*80+4*90+5*100) = 6/130 // 第一个伸缩项目缩小宽度 extendWidth = ( 400 - 250 ) * 6/130 ≈ 6.922 // 第一个伸缩项目压缩后的宽度 itemWidth = 60 - 6.922 = 53.078
计算后获得第一个伸缩项目压缩后的宽度是53.078px,和chrome上的盒子模型是同样的。
上面介绍的flex-grow
、flex-shrink
和flex-basis
有一个缩写的写法flex
。
flex
:flex-grow
[flex-shrink
] [flex-basis
]
flex
各类缩写的值
flex: initial
== flex: 0 1 auto
flex: none
== flex: 0 0 auto
flex: auto
== flex: 1 1 auto
flex: number
== flex: number 1 0%
在实际项目中,会直接写使用缩写的flex
来给伸缩项目分配空间,可是使用缩写属性会留下一些陷阱,致使表现的结果不尽如人意。
分别使用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 $i from 1 through 5 { .flexbox-item:nth-child(#{$i}){ background-color: rgba(35 * (6-$i), 20 * $i, 35 * $i,1); } }
每一个伸缩项目在原宽度上拉伸相同的宽度
经过上面的计算拉伸后的伸缩项目宽度,能够计算第一个伸缩项目拉伸后的宽度
// 项目容器宽度 container = 550 // 项目宽度或项目设置的flex-basis总和 itemSum = 60 + 70 + 80 + 90 + 100 = 400 // 第一个伸缩项目对应的flex-grow比例 flexRatio = 1 / ( 1 + 1 + 1 + 1 + 1 ) = 1/5 // 第一个伸缩项目扩展宽度 extendWidth = ( 550 - 400 ) * 1/5 = 30 // 第一个伸缩项目拉伸后的宽度 itemWidth = 60 + 30 = 90
而后咱们把flex-grow:1
替换成flex:1
,下面是表现的效果,伸缩项目拉伸后的宽度变成同样了。
从chrome的盒子模型可看到伸缩项目拉伸后宽度变成了110px
,伸缩容器等分了容器的宽度。
flex:1
展开后是flex:1 1 0%
,flex-grow:1
至关于flex:1 1 auto
,二者的区别在于flex-basis
的值不一样。flex:1
为项目宽度从新设置了宽度为0
,因此可分配空间为整个容器,从公式计算上能够更直观理解:
// 项目容器宽度 container = 550 // 项目宽度或项目设置的flex-basis总和 itemSum = 0 + 0 + 0 + 0 + 0 = 0 // 第一个伸缩项目对应的flex-grow比例 flexRatio = 1 / ( 1 + 1 + 1 + 1 + 1 ) = 1/5 // 第一个伸缩项目扩展宽度 extendWidth = ( 550 - 0 ) * 1/5 = 110 // 第一个伸缩项目拉伸后的宽度 itemWidth = 0 + 110 = 110
column-*在伸缩容器无效
float和clear在伸缩项目无效
vertical-align在伸缩项目无效
::first-line and ::first-letter在伸缩容器无效
<div class="flexbox-wrap"> <span class="flexbox-item">1</span> <span class="flexbox-item">2</span> 我是个假文本 <span class="flexbox-item">3</span> <span class="flexbox-item">4</span> <span class="flexbox-item">5</span> </div>
伸缩容器和伸缩项目的margin不会折叠
伸缩项目间的margin不会折叠
伸缩项目为行内元素要加display:block;或display:flex
欢迎关注:Leechikit
原文连接:segmentfault.com到此本文结束,欢迎提问和指正。写原创文章不易,若本文对你有帮助,请点赞、推荐和关注做者支持。