◆

CSS Flex 布局详解:flex-grow、flex-shrink、flex-basis

2023-02-02 01:370

flex-basis

  • 指定了 flex 元素在主轴方向上的初始大小
  • 如果不使用 box-sizing 改变盒模型的话,那么这个属性就决定了 flex 元素的内容盒(content-box)的尺寸。
  • 当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了 height) , flex-basis 具有更高的优先级. ::: demo [vanilla]
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div
      id="test-basis"
      style="display: flex;margin: 100px auto;width: 500px;height: 200px;background: black;;color: red"
    >
      <div
        class="inner"
        style="width: 200px;height: 100px;flex-basis: 300px;background: pink;"
      ></div>
      <div
        class="inner1"
        style="height: 100px;flex-basis: 200px;background: lightcyan;"
      >
        inner1
      </div>
    </div>
    <script>
      const inner = document
        .getElementById('test-basis')
        .getElementsByClassName('inner')[0];
      inner.innerText = 'inner:' + inner.offsetWidth;
      const inner1 = document
        .getElementById('test-basis')
        .getElementsByClassName('inner1')[0];
      inner1.innerText = 'inner1:' + inner1.offsetWidth;
    </script>
  </body>
</html>
{
  "show": true
}

:::

flex-grow

  • 该属性用来设置当父元素的宽度大于所有子元素的宽度的和时(即父元素会有剩余空间),子元素如何分配父元素的剩余空间。
  • flex-grow 的默认值为 0,意思是该元素不索取父元素的剩余空间,如果值大于 0,表示索取。值越大,索取的越厉害。 ::: demo [vanilla]
<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div
      id="test-grow"
      style="display: flex;justify-content: space-around;flex-wrap: wrap"
    >
      <div
        style="display: flex;width: 280px;height: 100px;background: black;color: red"
      >
        <div
          class="inner1"
          style="flex-basis: 100px;height: 100px;background: lightcyan;"
        ></div>
        <div
          class="inner2"
          style="flex-basis: 50px;height: 100px;background: pink;box-sizing: border-box"
        ></div>
      </div>

      <div
        style="display: flex;width: 280px;height: 100px;background: black;color: red"
      >
        <div
          class="inner1"
          style="flex-basis: 100px;flex-grow: 0;height: 100px;background: lightcyan;"
        ></div>
        <div
          class="inner2"
          style="flex-basis: 50px;flex-grow: 0;width: 100px;height: 100px;background: pink;"
        ></div>
      </div>

      <div
        style="display: flex;width: 280px;height: 100px;background: black;color: red"
      >
        <div
          class="inner1"
          style="flex-basis: 100px;flex-grow: 0;height: 100px;background: lightcyan;"
        ></div>
        <div
          class="inner2"
          style="flex-basis: 50px;flex-grow: 1;width: 100px;height: 100px;background: pink;"
        ></div>
      </div>

      <div
        style="display: flex;width: 280px;height: 100px;background: black;color: red"
      >
        <div
          class="inner1"
          style="flex-basis: 100px;flex-grow: 2;height: 100px;background: lightcyan;"
        ></div>
        <div
          class="inner2"
          style="flex-basis: 50px;flex-grow: 1;width: 100px;height: 100px;background: pink;"
        ></div>
      </div>
    </div>
    <script>
      const inner2 = document
        .getElementById('test-grow')
        .getElementsByClassName('inner2');
      for (let i = 0; i < inner2.length; i++) {
        inner2[i].innerText = 'inner2:' + inner2[i].clientWidth;
      }
      const inner1 = document
        .getElementById('test-grow')
        .getElementsByClassName('inner1');
      for (let i = 0; i < inner1.length; i++) {
        inner1[i].innerText = 'inner1:' + inner1[i].offsetWidth;
      }
    </script>
  </body>
</html>
{
  "show": true
}

::: 如果 inner1,inner2 都设索取剩余空间,inner1 设置 flex-grow 为 2,inner2 设置 flex-grow 为 1。 则最终 inner1 的大小为 自身宽度 (100+ inner1 获得的剩余空间的宽度(130 * (2/(1+2))=86.666 = 187 最终 inner2 的大小为 自身宽度 (50+ inner2 获得的剩余空间的宽度 (130 * (1/(1+2))=43.333 = 93

flex-shrink

  • 该属性用来设置,当父元素的宽度小于所有子元素的宽度的和时(即子元素会超出父元素),子元素如何缩小自己的宽度的。
  • flex-shrink 的默认值为 1,当父元素的宽度小于所有子元素的宽度的和时,子元素的宽度会减小。值越大,减小的越厉害。如果值为 0,表示不减小。

简单示例 ::: demo [vanilla]

<html>
  <head>
    <meta charset="UTF-8" />
    <title>Title</title>
  </head>
  <body>
    <div
      id="test-shrink"
      style="display: flex;justify-content: space-around;flex-wrap: wrap"
    >
      <div
        style="display: flex;width: 280px;height: 100px;background: black;color: red;"
      >
        <div
          class="inner"
          style="flex-basis: 100px;width: 80px;height: 100px;background: pink;"
        ></div>
        <div
          class="inner1"
          style="flex-basis: 200px;height: 100px;background: lightcyan;"
        ></div>
      </div>

      <div
        style="display: flex;width: 280px;height: 100px;background: black;color: red"
      >
        <div
          class="inner"
          style="flex-basis: 100px;flex-shrink: 1width: 80px;height: 100px;background: pink;"
        ></div>
        <div
          class="inner1"
          style="flex-basis: 200px;flex-shrink: 1height: 100px;background: lightcyan;"
        ></div>
      </div>

      <div
        style="display: flex;width: 280px;height: 100px;background: black;color: red"
      >
        <div
          class="inner"
          style="flex-basis: 100px;flex-shrink: 0;width: 80px;height: 100px;background: pink;"
        ></div>
        <div
          class="inner1"
          style="flex-basis: 200px;flex-shrink: 0;height: 100px;background: lightcyan;"
        ></div>
      </div>

      <div
        style="display: flex;width: 280px;height: 100px;background: black;color: red"
      >
        <div
          class="inner"
          style="flex-basis: 100px;flex-shrink: 1;width: 30px;height: 100px;background: pink;"
        ></div>
        <div
          class="inner1"
          style="flex-basis: 200px;flex-shrink: 0;height: 100px;background: lightcyan;"
        ></div>
      </div>
    </div>
    <script>
      const inner = document
        .getElementById('test-shrink')
        .getElementsByClassName('inner');
      for (let i = 0; i < inner.length; i++) {
        inner[i].innerText = 'inner:' + inner[i].offsetWidth;
      }
      const inner1 = document
        .getElementById('test-shrink')
        .getElementsByClassName('inner1');
      for (let i = 0; i < inner1.length; i++) {
        inner1[i].innerText = 'inner1:' + inner1[i].offsetWidth;
      }
    </script>
  </body>
</html>
{
  "show": true
}

:::

复杂示例 ::: demo [vanilla]

<!DOCTYPE html>
<html>
  <div
    id="test-flex"
    style="display: flex;width: 1500px;outline: 1px red solid;"
  >
    <div
      class="flexItem"
      style="flex-shrink: 2;flex-basis: 300px;margin: 0 10px;box-sizing: content-box;"
      title="300 - (550*600/2770) ≈ 180.866"
    >
      1
    </div>
    <div
      class="flexItem"
      style="flex-shrink: 2;flex-basis: 300px;padding: 0 20px;border: 5px #ccc solid;box-sizing: content-box;"
      title="300 - (550*600/2770) ≈ 180.866"
    >
      2
    </div>
    <div
      class="flexItem"
      style="flex-shrink: 2;flex-basis: 300px;padding: 0 20px;border: 5px #ccc solid;box-sizing: border-box;"
      title="300 - (550*500/2770) ≈ 200.722 - 20*2 - 10*2 = 150.722"
    >
      3
    </div>
    <div
      class="flexItem"
      style="flex-shrink: 1;flex-basis: 200px;padding: 0 10px;box-sizing: content-box;"
      title="200 - (550*200/2770) ≈ 160.288"
    >
      4
    </div>
    <div
      class="flexItem"
      style="flex-shrink: 1;flex-basis: 200px;border: 5px #ccc solid;margin: 0 10px;box-sizing: content-box;"
      title="200 - (550*200/2770) ≈ 160.288"
    >
      5
    </div>
    <div
      class="flexItem"
      style="flex-shrink: 1;flex-basis: 200px;border: 5px #ccc solid;margin: 0 10px;box-sizing: border-box;"
      title="200 - (550*190/2770) ≈ 162.274 - 5*2 = 152.274"
    >
      6
    </div>
    <div
      class="flexItem"
      style="flex-shrink: 2;flex-basis: 100px;border: 5px #ccc solid;box-sizing: content-box;"
      title="100 - (550*200/2770) ≈ 60.288"
    >
      7
    </div>
    <div
      class="flexItem"
      style="flex-shrink: 2;flex-basis: 100px;padding: 0 30px;margin: 0 10px;box-sizing: content-box;"
      title="100 - (550*200/2770) ≈ 60.288"
    >
      8
    </div>
    <div
      class="flexItem"
      style="flex-shrink: 2;flex-basis: 100px;padding: 0 30px;margin: 0 10px;box-sizing: border-box;"
      title="100 - (550*80/2770) ≈ 84.115 - 30*2 = 24.115"
    >
      9
    </div>
  </div>
  <script>
    const flexItems = document
      .getElementById('test-flex')
      .getElementsByClassName('flexItem');
    for (var i = 0; i < flexItems.length; i++) {
      flexItems[i].innerText = flexItems[i].offsetWidth;
    }
  </script>
</html>
{
  "show": true
}

::: 计算规则:

  • 父容器宽度:1500
  • 子容器所需宽度:(300+10*2) + (300+20*2+5*2) + (300) + (200+10*2) + (200+10*2+5*2) + (200+10*2) + (100+5*2) + (100+10*2+30*2) + (100+10*2)= 2050
    • 其中 box-sizing 为 border-box(代表 IE 盒模型)其 width 就是 width + margin,否则 width 为 width + padding + border + margin
  • 收缩系数:300*2 + 300*2 + (300-20*2-5*2)*2 + 200*1 + 200*1 + (200-5*2)*1 + 100*2 + 100*2 + (100-30*2)*2 = 2770
    • 标准盒模型: flex-basis * flex-shrink
    • IE 盒模型: (flex-basis - padding - border) * flex-shrink
  • 所需分配的宽度:1500 - 2050 = -550
  • 每个子容器的宽度:
    • 300 - 550*(600/2770) = 180.866 content-box
    • 300 - 550*(600/2770) = content:180.866 + padding:20 * 2 + border:5 * 2 = 230.866 content-box
    • 300 - 550*(500/2770) = content:200.722 border-box
    • 200 - 550*(200/2770) = 160.288 + padding:10 * 2 = 180.288 content-box
    • 200 - 550*(200/2770) = 160.288 + border:5 * 2 = 170.288 content-box
    • 200 - 550*(190/2770) = 162.274 border-box
    • 100 - 550*(200/2770) = 60.288 + border:5 * 2 = 70.288 content-box
    • 100 - 550*(200/2770) = 60.288 + padding:30 * 2 = 120.288 content-box
    • 100 - 550*(80/2770) = 84.115 border-box

flex 的简写

  • flex 是 flex-grow,flex-shrink, flex-basis 的简写
  • flex 取值为 none,则计算值为 0 0 auto
  • flex 取值为 auto,则计算值为 1 1 auto
  • flex 取值为一个非负数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%
  • flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1
  • flex 取值为两个非负数字,则视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%
  • flex 取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow 和 flex-basis 的值,flex-shrink 取 1
💬留言板0

还没有留言,来发表第一条吧~

PAGE LOAD / LIVECSS Flex 布局详解:flex-grow、flex-shrink、flex-basis加载中