Published on

flex:1 的等分机制

flex 属性的三个组成部分

flex 属性是以下三个子属性的简写: flex: <flex-grow> <flex-shrink> <flex-basis>;

flex-basis: 尺寸基准

flex-basis 定义了在分配剩余空间 (free space) 之前,一个 flex item 在主轴上的初始尺寸或“假设尺寸” (hypothetical size)

  • 默认值: auto
    • 如果元素显式设置了 widthheight(取决于主轴方向),flex-basis 的值就等于该尺寸。
    • 如果未设置 width/height,则其尺寸等于其内容的内在尺寸 (intrinsic size)
  • 优先级: 当 flex-basis 被设置为一个具体值(如 100px0%)时,其优先级高于 widthheight 属性。
flex-basis: 0 与最小尺寸 (Minimum Size)

flex-basis 设置为 0,意味着在空间分配算法的初始步骤中,该元素的尺寸被视为零,其内容大小被忽略。

但是,这并不意味着该元素在空间不足时,会被无限收缩至 0 像素。

默认情况下,flex item 的最小尺寸(min-widthmin-height)被设置为 auto,其值等于该 item 内部内容的最小内在尺寸(例如,最长的单词或一张图片的宽度)。Flexbox 算法在收缩 item 时,会尊重这个最小尺寸,不会让 item 收缩到比其内容还小,以防止内容溢出或变得不可读。

flex-basis

flex-grow: 增长因子

flex-grow 定义了当 flex 容器在主轴上存在剩余空间时,flex item 应如何“瓜分”这些空间。

  • 默认值: 0,表示即使有剩余空间,元素也不会放大。
  • 分配机制: 它是一个比例值。
    • 如果所有 flex item 的 flex-grow 值总和大于等于 1,它们会按各自 flex-grow 值的比例来分配所有剩余空间。例如,A、B 两个 item 的 flex-grow 分别为 21(总和为 3),则 A 会获得 2/3 的剩余空间,B 会获得 1/3。
    • 如果所有 flex item 的 flex-grow 值总和小于 1,它们将不会完全占据所有剩余空间。它们只会占据“总和百分比”的剩余空间。例如,A、B 的 flex-grow 分别为 0.20.3(总和为 0.5),它们将总共占据 50% 的剩余空间,剩余 50% 的空间会留白。在这 50% 的已分配空间中,A 会获得 2/5,B 会获得 3/5。
flex-grow

flex-shrink: 收缩因子

flex-shrink 定义了当 flex 容器在主轴上的空间不足时,flex item 应如何“分摊”这个超出的空间。

  • 默认值: 1,表示默认情况下,所有 item 会等比例收缩。
  • 分配机制: 其计算为 (flex-shrink × flex-basis) 的比例值。例如,两个元素分别为 flex-shrink: 1, flex-basis: 200pxflex-shrink: 2, flex-basis: 100px,收缩比例为 200:200(即 1:1),而非简单的 1:2。

Flex 布局算法与 flex: 1

浏览器确定 flex item 最终尺寸的算法流程如下:

flex: 1 的精确含义

flex: 1flex: 1 1 0% 的简写,这意味着:

  • flex-grow: 1: 该 item 会参与剩余空间的分配。
  • flex-shrink: 1: 当空间不足时,该 item 会等比例收缩。
  • flex-basis: 0%: 该 item 的初始尺寸被假定为 0。

当一个容器内的所有子元素都设置为 flex: 1 时,它们的 flex-basis 总和为 0,这意味着容器的全部可用空间都被视为“剩余空间”。由于它们的 flex-grow 值都为 1,这些剩余空间将被平均分配给所有子元素,从而实现了子元素的等分布局。

flex: 1 实现等分布局

<div class="flex h-24 border">
  <div class="flex-1 bg-blue-200">Item 1</div>
  <div class="flex-1 bg-green-200">Item 2</div>
  <div class="flex-1 bg-red-200">Item 3</div>
</div>

在上述代码中,三个子元素会平分父容器的宽度(因为默认主轴是 row,所以 flex: 1 控制的是宽度,但如果父容器有固定高度,子元素会拉伸)。

flex-wrap 的影响与 Grid 的对比

Flexbox 的尺寸分配算法是逐行或逐列独立计算的。

flex: 1 在换行布局中的局限性

当父容器设置了 flex-wrap: wrap 时,flex: 1 的等分效果仅在同一行或同一列内有效。不同行/列的“剩余空间”是独立计算的,如果每行的 item 数量不同,它们的最终尺寸也会不同。

<div style="display: flex; flex-wrap: wrap; width: 220px; border: 2px solid black; box-sizing: border-box;">
  <!-- 第一行:3个元素,每个最小内容宽度50px,加上padding和border,总最小宽度72px -->
  <div style="flex: 1; min-width: 50px; background: lightblue; padding: 10px; border: 1px solid darkblue; text-align: center;">1</div>
  <div style="flex: 1; min-width: 50px; background: lightblue; padding: 10px; border: 1px solid darkblue; text-align: center;">2</div>
  <div style="flex: 1; min-width: 50px; background: lightblue; padding: 10px; border: 1px solid darkblue; text-align: center;">3</div>
  
  <!-- 第二行:2个元素,每个最小宽度50px,但剩余空间被等分,所以每个元素实际宽度更大 -->
  <div style="flex: 1; min-width: 50px; background: lightgreen; padding: 10px; border: 1px solid darkgreen; text-align: center;">4</div>
  <div style="flex: 1; min-width: 50px; background: lightgreen; padding: 10px; border: 1px solid darkgreen; text-align: center;">5</div>
</div>
flex-wrap
二维布局的权威方案:CSS Grid

如果需要创建一个跨越多行多列的、尺寸严格统一的网格系统,CSS Grid 布局是比 Flexbox 更合适、更强大的解决方案。Flexbox 的核心优势在于一维(单行或单列)的对齐和空间分配。