flex 可以说是一次性解决了前端布局的所有的问题(当然,并没有完全解决,要不然也不会有 grid layout 了),以前很难实现的布局效果在 flex 下简直不能更简单,以至于一些其它平台也开始吸纳 flex 的布局思想,也有些开源项目把 flex 的布局方式移植到其它平台。
本文的示例布局如下:
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
flex-grow的计算方式
当子元素宽度的总和 < 父元素宽度,那么此时就会按照flex-grow进行伸缩布局。样式如下:
.container {
width: 600px;
height: 300px;
display: flex;
}
.left {
width: 300px;
flex-grow: 1;
background-color: orange;
}
.right {
width: 200px;
flex-grow: 2;
background-color: pink;
}
可以看到,子元素left宽度+right宽度 = 500px
。宽度总和是没有父元素container
的宽度大的,剩余的100px将会根据flex-grow平分分配给left和right元素。left的flex-grow = 1,right的flex-grow = 2,所以,剩余空间被分配为3份,1份分给left,2份分给right,所以left、right宽度的计算公式如下:
left: 300 + ( 600 - ( 300 + 200 ) ) * 1 / 3 = 333.33
right: 200 + ( 600 - ( 300 + 200 ) ) * 2 / 3 = 266.67
flex-shrink的计算方式
当子元素宽度的总和 > 父元素宽度,那么此时就会按照flex-shrink进行压缩布局。样式如下:
.container {
width: 600px;
height: 300px;
display: flex;
}
.left {
width: 500px;
flex-grow: 1;
flex-shrink: 2;
background-color: orange;
}
.right {
width: 400px;
flex-grow: 2;
flex-shrink: 1;
background-color: pink;
}
可以看到,left和right的宽度总和(900)明显大于父元素的宽度600,所以需要按照shrink进行压缩。计算方法是宽度 - 超出宽度 x (权重宽度 / 总权重宽度)
// 超出宽度
const overWidth = Math.abs(600 - (500 + 400)) = 300
// 总权重宽度
const totalWeightWidth = 500 x 2 + 400 x 1 = 1400
// 计算left宽度 right宽度
const left = 500 - 300 * ((2 * 500 ) / 1400) = 285.71
const right = 400 - 300 * ((1 * 400 ) / 1400) = 314.29
flex-basis
flex-basis的默认值为auto,他指定了 flex 元素在主轴方向上的初始大小。
- flex-basis为0时,那么元素初始大小尽可能的小
- flex-basis为auto时,那么元素宽度会交给flex布局进行自适应
- flex-basis为指定大小时,那么元素会按照这个初始大小上在flex布局中进行改变
flex
flex属性是flex-grow flex-shrink flex-basic
的简写,其中后两个属性值可以省略。其默认值flex: 0 1 auto
参考
https://zhuanlan.zhihu.com/p/24372279
面试题目
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/381
https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/382