flex的伸缩计算

417 阅读3分钟

案例

下面这段代码估计大家经常会用到,目的是让.main自适应。

.ctn {
    display: flex;
    width: 500px;
    height: 200px;
}
.main {
    flex: 1;
    background-color: red;
}
.left {
    width: 100px;
    background-color: yellow;
}
.right {
    width: 200px;
    background-color: green;
}
<div class="ctn">
    <div class="left"></div>
    <div class="main"></div>
    <div class="right"></div>
</div>

截屏2022-02-09 下午4.26.25.png 大家都知道设置flex: 1可以让元素自适应宽度,但却不知道其原理,比如我们把.ctn的宽度设为200px,再看看效果,我们会发现.main消失了 截屏2022-02-09 下午4.26.36.png

规则

flex其实是flex-grow flex-shrink flex-basis的缩写,默认是0 1 auto 其它还有flex: 0 flex: none flex: auto可参考表格

flexflex-growflex-shrinkflex-basis
default01auto
1110%
0010%
none00auto
auto11auto

记起来也很简单

  1. flex: num === flex: num 1 0%
  2. flex: none伸缩是0 flex: auto伸缩是1

分析

让我们回到案例,我们给.main设置了flex: 1,相当于flex: 1 1 0% 伸缩都是1,总有点矛盾,到底是伸还是缩?这要取决于flex盒子的剩余宽度

flex盒子宽度过剩时,会使用子元素的flex-grow计算,在flex盒子的宽度不足时,会使用子元素的flex-shrink计算

1.当.ctn宽度为500px时,

  • 盒子剩余宽度为500 - 500 * 0% - 100- 200 = 200
  • .left.right没有设置相当于flex: 0 1 auto,所以总放大比例为1 + 0 + 0 = 1
  • .left总宽度100 + 200 * (0 / 1) = 100
  • .right总宽度200 + 200 * (0 / 1) = 200
  • .main总宽度500 * 0% + 200 * (1 / 1) = 200
  • 总结计算公式:基础宽度 + 盒子剩余宽度 * (放大比例 / 总放大比例)
  1. .ctn宽度为200px时,
  • 盒子不足宽度为500 * 0% + 100 + 200 - 200 = 100
  • .left.right没有设置相当于flex: 0 1 auto,所以总缩放权重为500 * 0% * 1 + 100 * 1 + 200 * 1 = 300
  • .left总宽度100 - 100 * (100 * 1 / 300) = 66.66
  • .right总宽度200 - 100 * (200 * 1 / 300) = 133.33
  • .main总宽度500 * 0% - 100 * (0 * 1 / 300) = 0
  • 总结计算公式:基础宽度 - 盒子不足宽度 * (缩放权重 / 总缩放权重)

虽然仅仅只有flex: 1一行代码,但其实是包含了复杂的计算的

最后我们在看一个例子

<div class="ctn">
    <div class="item1"></div>
    <div class="item2"></div>
    <div class="item3"></div>
    <div class="item4"></div>
    <div class="item5"></div>
    <div class="item6"></div>
</div>
.ctn {
  margin: 100px;
  display: flex;
  width: 500px;
  height: 500px;
}
.item1 {
  width: 100px;
  flex: 1;
  background-color: red;
}
.item2 {
  width: 100px;
  flex: 0;
  background-color: green;
}
.item3 {
  width: 100px;
  flex: none;
  background-color: yellow;
}
.item4 {
  width: 100px;
  flex: auto;
  background-color: pink;
}
.item5 {
  width: 200px;
  flex: 1 1 100px;
  background-color: gray;
}
.item6 {
  width: 200px;
  flex: 2 1 20%;
  background-color: blue;
}
  • 先结合flex-basiswidth计算总宽度500 * 0% + 500 * 0% + 100 + 100 + 100 + 500 * 20% = 400
  • 剩余宽度500 - 400 = 100,使用放大计算方式
  • 总放大比例1 + 0 + 0 + 1 + 1 + 2 = 5
  • item1宽度500 * 0% + 100 * (1 / 5) = 20
  • item2宽度500 * 0% + 100 * (0 / 5) = 0
  • item3宽度100 + 100 * (0 / 5) = 100
  • item4宽度100 + 100 * (1 / 5) = 120
  • item5宽度100 + 100 * (1 / 5) = 120
  • item6宽度500 * 50% + 100 * (2 / 5) = 140

截屏2022-02-09 下午5.56.04.png

需要注意flex-basiswidth的取值方式:

  • flex-basis为百分比时,按父元素宽度 * 百分比
  • flex-basis为具体px时,按具体px
  • flex-basis为auto或者没设置时,按width