Flexbox布局的正确使用姿势

在项目中,我们还会大量使用到flexbox的新旧属性,但大多数人一般只会写新属性,旧属性交由autoprefixer处理,但其实完成同样功能的新旧属性表现形式却不尽相同。还有部分人只使用“万能”的flex:number属性为伸缩项目分配空间,但有些特殊情景却无法满足,此文为此梳理了flexbox的新旧属性区别和分配空间的原理,为大家用flexbox布局的项目通通渠。

在项目中,我们还会大量使用到flexbox的新旧属性,但大多数人一般只会写新属性,旧属性交由autoprefixer处理,但其实完成同样功能的新旧属性表现形式却不尽相同。还有部分人只使用“万能”的flex:number属性为伸缩项目分配空间,但有些特殊情景却无法满足,此文为此梳理了flexbox的新旧属性区别和分配空间的原理,为大家用flexbox布局的项目通通渠。

在项目中,我们还会大量使用到flexbox的新旧属性,但大多数人一般只会写新属性,旧属性交由autoprefixer处理,但其实完成同样功能的新旧属性表现形式却不尽相同。还有部分人只使用“万能”的flex:number属性为伸缩项目分配空间,但有些特殊情景却无法满足,此文为此梳理了flexbox的新旧属性区别和分配空间的原理,为大家用flexbox布局的项目通通渠。

Flexbox兼容性

PC端的兼容性

Flexbox布局的正确使用姿势

移动端的兼容性

Flexbox布局的正确使用姿势

如上图,为了兼容IE10-11和Android4.3-,UC,我们仍需要使用Flexbox的旧属性。

Flexbox新旧属性

Flexbox的新属性提供了很多旧版本没有的功能,但是目前Android4.x和UC仍有一定市场占有率需要兼容,因此目前只使用新旧属性都有的功能。

能实现相同功能的Flexbox新旧属性如下表:

Flexbox布局的正确使用姿势

但想象是美好的,现实是残酷的,新旧属性里有那么几个顽固分子并不能乖乖的表现的一样,总有那么一点不同。

下面我们来看看是哪些新旧属性有不同:

flex-direction:row-reverse vs box-orient:horizontal;box-direction:reverse

相同点:改变主轴方向和伸缩项目的排列顺序;在ltr下伸缩项目从右到左排列。

不同点:

flex-direction:row-reverse:第一个伸缩项目向主轴起点对齐

Flexbox布局的正确使用姿势

box-orient:horizontal;box-direction:reverse:最后一个伸缩项目向主轴终点对齐

Flexbox布局的正确使用姿势

flex-direction:column-reverse vs box-orient:vertical;box-direction:reverse

相同点:改变主轴方向和伸缩项目的排列顺序;在ltr下伸缩项目从下到上排列。

不同点:

flex-direction:column-reverse:第一个伸缩项目向主轴起点对齐。

Flexbox布局的正确使用姿势

box-orient:vertical;box-direction:reverse:最后一个伸缩项目向主轴终点对齐。

Flexbox布局的正确使用姿势

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分配空间原理

影响Flexbox布局分配空间的属性有三个,分别是flex-grow、flex-shrink和flex-basis。

  • flex-grow:当伸缩项目在主轴方向的总宽度
  • flex-shrink:当伸缩项目在主轴方向的总宽度 > 伸缩容器,伸缩项目根据缩小因素分配总宽度超出伸缩容器的空间。
  • flex-basis:伸缩基础,在进行计算剩余空间或超出空间前,给伸缩项目重新设置一个宽度,然后再计算。

我们先来看看如何计算计算拉伸后的伸缩项目宽度,先简单明了的给个公式,再通过栗子来验证。

伸缩项目扩展宽度 = (项目容器宽度 – 项目宽度或项目设置的flex-basis总和) * 对应的flex-grow比例

拉伸后伸缩项目宽度 = 原伸缩项目宽度 + 扩展宽度

  1. .flexbox-wrap{
  2. width:550px;
  3. display:flex;
  4. }
  5. .flexbox-item{
  6. &:nth-child(1){
  7. width:60px;
  8. }
  9. &:nth-child(2){
  10. width:70px;
  11. }
  12. &:nth-child(3){
  13. flex-basis:80px;
  14. }
  15. &:nth-child(4){
  16. flex-basis:90px;
  17. }
  18. &:nth-child(5){
  19. flex-basis:100px;
  20. }
  21. }
  22. @for$ifrom1through5{
  23. .flexbox-item:nth-child(#{$i}){
  24. flex-grow:$i;
  25. background-color:rgba(35*(6-$i),20*$i,35*$i,1);
  26. }
  27. }

Flexbox布局的正确使用姿势

我们来计算一下上面栗子中第一个伸缩项目拉伸后的宽度。

对应着公式一步步计算:

  1. //项目容器宽度
  2. container=550
  3. //项目宽度或项目设置的flex-basis总和
  4. itemSum=60+70+80+90+100=400
  5. //第一个伸缩项目对应的flex-grow比例
  6. flexRatio=1/(1+2+3+4+5)=1/15
  7. //第一个伸缩项目扩展宽度
  8. extendWidth=(550-400)*1/15=10
  9. //第一个伸缩项目拉伸后的宽度
  10. itemWidth=60+10=70

计算后得到第一个伸缩项目拉伸后的宽度是70px,我们通过chrome上的盒子模型来看看是否正确

Flexbox布局的正确使用姿势

chrome计算的结果和我们计算的结果是一致的。

根据拉伸的计算公式是不是很容易就能推演出压缩的计算公式呢?

伸缩项目缩小宽度 = (项目宽度或项目设置的flex-basis总和 – 项目容器宽度) * 对应的flex-shrink比例

压缩后伸缩项目宽度 = 原伸缩项目宽度 – 缩小宽度

继续用个栗子来验证公式是否正确

  1. .flexbox-wrap{
  2. width:250px;
  3. display:flex;
  4. }
  5. .flexbox-item{
  6. &:nth-child(1){
  7. width:60px;
  8. }
  9. &:nth-child(2){
  10. width:70px;
  11. }
  12. &:nth-child(3){
  13. flex-basis:80px;
  14. }
  15. &:nth-child(4){
  16. flex-basis:90px;
  17. }
  18. &:nth-child(5){
  19. flex-basis:100px;
  20. }
  21. }
  22. @for$ifrom1through5{
  23. .flexbox-item:nth-child(#{$i}){
  24. flex-shrink:$i;
  25. background-color:rgba(35*(6-$i),20*$i,35*$i,1);
  26. }
  27. }

我们来计算一下上面栗子中第一个伸缩项目压缩后的宽度。

对应着公式一步步计算:

  1. //项目容器宽度
  2. container=250
  3. //项目宽度或项目设置的flex-basis总和
  4. itemSum=60+70+80+90+100=400
  5. //第一个伸缩项目对应的flex-shrink比例
  6. flexRatio=1/(1+2+3+4+5)=1/15
  7. //第一个伸缩项目缩小宽度
  8. extendWidth=(400-250)*1/15=10
  9. //第一个伸缩项目压缩后的宽度
  10. itemWidth=60-10=50

计算后得到第一个伸缩项目压缩后的宽度是50px,我们通过chrome上的盒子模型来看看是否正确

Flexbox布局的正确使用姿势

chrome计算的结果和我们计算的结果不一样。

[[196343]]

伸缩项目压缩的计算方式和拉伸的不一样,是因为压缩会有极端情况,我们把第一个伸缩项目的flex-shrink修改为10,此时缩小宽度为( 400 - 250 ) * ( 10 / 24) = 62.5,缩小的宽度比原宽度要大,计算的压缩后的宽度变成了负数。

为了避免这种极端情况,计算缩小比例是要考虑伸缩项目的原宽度。

正确的公式是这样的

伸缩项目缩小宽度 = (项目宽度或项目设置的flex-basis总和 – 项目容器宽度) (对应的flex-shrink 项目宽度或项目设置的flex-basis比例)

压缩后伸缩项目宽度 = 原伸缩项目宽度 – 缩小宽度

对应着公式一步步计算:

  1. //项目容器宽度
  2. container=250
  3. //项目宽度或项目设置的flex-basis总和
  4. itemSum=60+70+80+90+100=400
  5. //第一个伸缩项目对应的flex-shrink比例
  6. flexRatio=(1*60)/(1*60+2*70+3*80+4*90+5*100)=6/130
  7. //第一个伸缩项目缩小宽度
  8. extendWidth=(400-250)*6/130≈6.922
  9. //第一个伸缩项目压缩后的宽度
  10. itemWidth=60-6.922=53.078

计算后得到第一个伸缩项目压缩后的宽度是53.078px,和chrome上的盒子模型是一样的。

Flexbox属性缩写陷阱

上面介绍的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拉伸伸缩项目的效果

  1. .flexbox-wrap{
  2. width:550px;
  3. display:flex;
  4. }
  5. .flexbox-item{
  6. flex-grow:1;
  7. &:nth-child(1){
  8. width:60px;
  9. }
  10. &:nth-child(2){
  11. width:70px;
  12. }
  13. &:nth-child(3){
  14. width:80px;
  15. }
  16. &:nth-child(4){
  17. width:90px;
  18. }
  19. &:nth-child(5){
  20. width:100px;
  21. }
  22. }
  23. @for$ifrom1through5{
  24. .flexbox-item:nth-child(#{$i}){
  25. background-color:rgba(35*(6-$i),20*$i,35*$i,1);
  26. }
  27. }

每个伸缩项目在原宽度上拉伸相同的宽度

Flexbox布局的正确使用姿势

通过上面的计算拉伸后的伸缩项目宽度,可以计算第一个伸缩项目拉伸后的宽度

  1. //项目容器宽度
  2. container=550
  3. //项目宽度或项目设置的flex-basis总和
  4. itemSum=60+70+80+90+100=400
  5. //第一个伸缩项目对应的flex-grow比例
  6. flexRatio=1/(1+1+1+1+1)=1/5
  7. //第一个伸缩项目扩展宽度
  8. extendWidth=(550-400)*1/5=30
  9. //第一个伸缩项目拉伸后的宽度
  10. itemWidth=60+30=90

Flexbox布局的正确使用姿势

然后我们把flex-grow:1替换成flex:1,下面是表现的效果,伸缩项目拉伸后的宽度变成一样了。

Flexbox布局的正确使用姿势

从chrome的盒子模型可看到伸缩项目拉伸后宽度变成了110px,伸缩容器等分了容器的宽度。

Flexbox布局的正确使用姿势

flex:1展开后是flex:1 1 0%,flex-grow:1相当于flex:1 1 auto,两者的区别在于flex-basis的值不同。flex:1为项目宽度重新设置了宽度为0,所以可分配空间为整个容器,从公式计算上可以更直观理解:

  1. //项目容器宽度
  2. container=550
  3. //项目宽度或项目设置的flex-basis总和
  4. itemSum=0+0+0+0+0=0
  5. //第一个伸缩项目对应的flex-grow比例
  6. flexRatio=1/(1+1+1+1+1)=1/5
  7. //第一个伸缩项目扩展宽度
  8. extendWidth=(550-0)*1/5=110
  9. //第一个伸缩项目拉伸后的宽度
  10. itemWidth=0+110=110

需要注意的Flexbox特性

无效属性

  • column-*在伸缩容器无效
  • float和clear在伸缩项目无效
  • vertical-align在伸缩项目无效
  • ::first-line and ::first-letter在伸缩容器无效

伸缩容器中的非空字符文本节点也是伸缩项目

1 2 我是个假文本 3 4 5

Flexbox布局的正确使用姿势

margin折叠

  • 伸缩容器和伸缩项目的margin不会折叠
  • 伸缩项目间的margin不会折叠

旧版Flexbox的BUG

伸缩项目为行内元素要加display:block;或display:flex

©本文为清一色官方代发,观点仅代表作者本人,与清一色无关。清一色对文中陈述、观点判断保持中立,不对所包含内容的准确性、可靠性或完整性提供任何明示或暗示的保证。本文不作为投资理财建议,请读者仅作参考,并请自行承担全部责任。文中部分文字/图片/视频/音频等来源于网络,如侵犯到著作权人的权利,请与我们联系(微信/QQ:1074760229)。转载请注明出处:清一色财经

(0)
打赏 微信扫码打赏 微信扫码打赏 支付宝扫码打赏 支付宝扫码打赏
清一色的头像清一色管理团队
上一篇 2023年5月4日 23:55
下一篇 2023年5月4日 23:55

相关推荐

发表评论

登录后才能评论

联系我们

在线咨询:1643011589-QQbutton

手机:13798586780

QQ/微信:1074760229

QQ群:551893940

工作时间:工作日9:00-18:00,节假日休息

关注微信