Published on

我承认,我并不理解flex-basis, flex-grow和flex-shrink

Authors
  • avatar
    Name
    Joy Peng
    Twitter

Introduction

正如我们所知,flexbox中的所有内容都与主轴交叉轴挂钩。例如justify-content将沿主轴分布子项,align-items将沿交叉轴分布子项。

widthheight却不遵循这个规则,它们是基于块级元素的,而不是基于flex容器的,widthheight永远都分别指定长和宽,并不会根据主轴和交叉轴的方向而改变。

flex-basis是什么?

flex-basis类似于widthheight,但是它是基于flex容器的,在flex row中和width执行相同的操作;在flex column中和height执行相同的操作。

它允许我们设置元素在主轴方向上的假设大小。假如我们给一个元素设置了flex-basis: 200px,那么这个元素将会尽可能在主轴上占据200px的空间。但这只是一个建议而不是硬性约束,如果没有足够的空间,为了避免溢出,元素可能会变小。

TIP

  1. flex-basis的默认值是auto,这意味着元素将根据其内容的大小来决定其大小。
  2. flex-basis若设置为0,则由 flex-grow 和 flex-shrink 决定最终尺寸。
  3. 如果同时设置了widthflex-basisflex-basis会覆盖width,即使 width 被放在 flex-basis 之后声明。
  4. 如果同时设置flex-basismin-widthmin-width能够限制flex元素最小的宽度,而flex-basis则是一个建议值。
<style>
  .dice {
    display: flex;
    width: 300px;
  }
  .dot {
    width: 1000px;
    /* min-width: 110px; */
    flex-basis: 150px;
    height: 100px;
    background-color: pink;
  }
</style>
<body>
  <div class="dice">
    <div class="dot"></div>
    <div class="dot"></div>
    <div class="dot"></div>
  </div>
</body>

在这个例子中,.dice宽度为300,.dotflex-basis为150,三个.dot元素将会尽可能占据150px的空间,但是由于.dice的宽度只有300px,所以.dot元素会被压缩,变成每个100px。 width不管设置得多大,都不会影响.dot的大小,因为flex-basis会覆盖width

但假如我们加上min-width:110px.dot元素的最小宽度将会被限制在110px,而不会继续缩小。

flex-grow和flex-shrink

flex-grow

默认情况下,Flex 上下文中的元素将沿主轴缩小到最小舒适尺寸(默认值flex-grow:0)。这通常会创造额外的空间。

我们可以使用flex-grow属性指定如何消耗该空间:

假如我们有一个flex容器,里面有三个子元素,它们的flex-grow属性分别为1、2、0,那么它们将会占据的额外空间比例为1:2:0,即第一个元素占据1/3的空间,第二个元素占据2/3的空间,第三个元素不占据空间。

flex-shrink

假如flex子项的总宽度大于flex容器的宽度,那么flex子项将会被压缩,flex-shrink属性指定了子项在这种情况下的压缩比例。

<style>
  .dice {
    display: flex;
    width: 300px;
  }
  .dot {
    height: 100px;
    background-color: pink;
  }

  .dot:nth-child(1) {
    flex-basis: 300px;
    flex-shrink: 3;
  }

  .dot:nth-child(2) {
    flex-basis: 150px;
    flex-shrink: 1;
  }
</style>
<body>
  <div class="dice">
    <div class="dot"></div>
    <div class="dot"></div>
  </div>
</body>

由于子项的总宽度为450px,大于flex容器的300px,所以.dot元素将会被压缩150px。

由于两个子项的flex-shrink属性分别为3和1,所以第一个子项将会被压缩 150 / (3+1) * 3 = 112.5px,第二个子项将会被压缩 150 / (3+1) = 37.5px。

最后第一个子项的宽度为187.5px,第二个子项的宽度为112.5px。

小结

  1. 互斥关系 flex-grow控制当子项的总宽度小于flex容器的宽度时,子项如何分配额外的空间;flex-shrink控制当子项的总宽度大于flex容器的宽度时,子项如何被压缩。

这意味着这两个属性一次只能有一个处于活动状态,因为它们是互斥的。

  1. 防止收窄 flex-shrink属性的默认值是1,这意味着子项将会被压缩,但是如果我们不希望某些子项被压缩,例如圆形的头像,我们不希望它被压成椭圆,可以将flex-shrink设置为0。

flex:1

flexflex-growflex-shrinkflex-basis的缩写,它的默认值是0 1 auto,这意味着元素不会增长,但会收缩,且flex-basisauto,根据元素的内容来决定。

flex:1flex:1 1 0的简写。flex: 1 的含义是:该项目会在容器中占据可用的剩余空间,并在空间不足时进行收缩。项目的初始尺寸为 0,完全依赖弹性布局规则进行空间分配

参考资料

  1. https://www.joshwcomeau.com/css/interactive-guide-to-flexbox/