[译] width 与 flex-basis 的区别

7,506 阅读5分钟

原文:The Difference Between Width and Flex Basis,from gedd.ski

摄影 | GoranH

这个问题很多人问起过我,实际上,当我对使用 Flexbox 还不太熟悉的时候,我谷歌过这个问题很多次。查看下我的谷歌搜索历史,上一年我曾四次搜索类似“flex-basis vs width vs min-width”的问题。废话少说!今天让我来回答这个问题,希望大家以后不用再搜索了。

Flex 项目公式

这是需要记忆的一个公式:

content -> width -> flex-basis(受到 max|min-width 的制约)

在决定 Flex 项目的尺寸方面,记住很重要的一点,就是最终尺寸(final flex-basis)会受 min-widthmax-width 属性限制。

注意:Flexbox 规范称之为“假想的主轴尺寸”,但是把它当做最终尺寸更容易我们理解。

如果未指定 flex-basisflex-basis 将回退到 width 属性。如果未指定 width 属性,flex-basis 将回退到基于 Flex 项目内容的计算宽度值(computed width)。

为了讲清除这个公式,我们使用 1000px 宽、包含一些 Flex 项目的 Flex 容器来说明:

container {
  display: flex;
  width: 1000px;
}

设置宽度

我们将 Flex 项目设置为 200px × 200px 的大小。

item {
  width: 200px;
  height: 200px;
}

现在,Flex 容器的尺寸足够装得下这些项目,我们给放进去。

这个例子里,我们没有为 Flex 项目指定 flex-basis(也就是取默认的 flex-basis: auto),因此基础尺寸会回退到 width(200px)。

此时,设置的 width 等同于设置 flex-basis

设置 flex-basis

下面我们再为 Flex 项目指定 flex-basis,看看会产生什么效果。

item {
  width: 30px;
  flex-basis: 250px;
}

可以看见,指定了 flex-basis 后,width 属性被忽略、不再起作用(相当于没有设置)。

item {
  flex-basis: 250px;
}

每个项目的最终尺寸是 250px。因为容器空间还是足够,所以项目放在容器里还是没问题的。

记住 Flex 项目的公式:

content -> width -> flex-basis(受到 max|min-width 的制约)

我们关心的是最终尺寸。最佳实践是使用 flex-basis 而非 widthheight。特别是,Safari 浏览器上还有一个古老的 bug:在使用了 height 而非 flex-basis 属性的 Flex 项目上 felx-shrink 属性不会生效。

flex-basis 受限于 max-width

Flex 项目的最终尺寸会受到 min-widthmax-width 属性影响。我们在 Flex 项目上设置 max-width 看一下:

item {
  flex-basis: 250px;
  max-width: 100px;
}

虽然 flex-basis 设置了 250px,但是却达到了 100pxmax-width 限制。因此最终尺寸是 100px,此时,Flex 项目还是能很好的放在 Flex 容器中的:

现在我们再设置 min-width 看下对最终尺寸的影响:

item {
  flex-basis: 100px;
  min-width: 250px;
}

虽然指定了 flex-basis: 100px,但是因为不能比 250pxmin-wdith 更小。因此,最终尺寸是 250px,Flex 项目能正好装在 Flex 容器中:

So,flex-basis 到底是什么?

现在我们知道了在 flex-basis 未指定的情况下,width 是它的回退方案,min-widthmax-width 是限制了最终 尺寸的上限和下限。So,flex-basis 到底是什么?

在上图里,你也可能注意到了,放入 Flex 容器之前,我们可视化了 Flex 项目的大小。之所以这样做,就是为了说明这就是 flex-basis即 Flex 项目放入 Flex 容器之前的尺寸(译者注:也就是项目的 max-content 大小)。这是 Flex 项目的理想或者说假想尺寸。但是为 flex-basis 指定的值不能保证就是 Flex 项目的最终尺寸!一旦我们将 Flex 项目放入 Flex 容器之后,事情就有改变了。上例中,Flex 容器的尺寸是刚刚好的,因此项目放在里面都是 OK 的,因为所有项目的最终尺寸加起来正好是 Flex 容器的宽度(1000px)。这很好,但通常所有 Flex 项目的 felx-basis 相加之后,Flex 容器不是空间不足就是空间过剩,而不是像这样刚刚好。

当空间不够的时候

假设我们像容器中放置了更多 flex-basis: 200px 的项目:

在放入容器之前,它们中的每一个都占据 200px 的尺寸,一共是 1600px。但是我们的容器只有 1000px 宽。结果是,我们没有足够的空间装得下这么多 Flex 项目,结果 Flex 项目默认会收缩以便适应不足的容器尺寸:

所有项目的起始宽度是 200px,因为空间不够,所以 Flex 项目开始收缩以适应容器空间(变为每个 125px)。flex-shrink 用于控制收缩比例。可以通过给 flex-shrink 指定一个更大或更小的值来控制收缩的程度,甚至可以设置为 0,表示不许收缩。

当有剩余空间的时候

也有时候,当我们把所有 Flex 项目的最终 flex-basis 加到一起后,容器还有剩余空间。

item {
  flex-basis: 100px;
}

我们可以指定我们的 Flex 项目在放入 Flex 容器之后伸展,来占据剩余空间,这是通过 flex-grow 属性控制的,此属性默认为 0,表示不会伸展。下例中,我们为每个 Flex 项目都设置了 flex-grow: 1(以相同比例伸展)来占据剩余空间。

item {
  flex-basis: 100px;
  flex-grow: 1;
}

增长和收缩是 Flexbox 布局的一大亮点,也是 Flexbox 在响应式 UI 设计方面如此出色的原因。

width vs flex-basis

现在能够区分 widthflex-basis 了吧,min-widthmax-width 会限制最终的尺寸。而当 flex-directioncolumncolumn-reverse 的时候,那就是 flex-basisheight 的关系了。

(完)