原文: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-width
和 max-width
属性限制。
注意:Flexbox 规范称之为“假想的主轴尺寸”,但是把它当做最终尺寸更容易我们理解。
如果未指定 flex-basis
,flex-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
而非 width
或 height
。特别是,Safari 浏览器上还有一个古老的 bug:在使用了 height
而非 flex-basis
属性的 Flex 项目上 felx-shrink
属性不会生效。
flex-basis 受限于 max-width
Flex 项目的最终尺寸会受到 min-width
和 max-width
属性影响。我们在 Flex 项目上设置 max-width
看一下:
item {
flex-basis: 250px;
max-width: 100px;
}
虽然 flex-basis
设置了 250px
,但是却达到了 100px
的 max-width
限制。因此最终尺寸是 100px
,此时,Flex 项目还是能很好的放在 Flex 容器中的:
现在我们再设置 min-width
看下对最终尺寸的影响:
item {
flex-basis: 100px;
min-width: 250px;
}
虽然指定了 flex-basis: 100px
,但是因为不能比 250px
的 min-wdith
更小。因此,最终尺寸是 250px
,Flex 项目能正好装在 Flex 容器中:
So,flex-basis 到底是什么?
现在我们知道了在 flex-basis
未指定的情况下,width
是它的回退方案,min-width
和 max-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
现在能够区分 width
和 flex-basis
了吧,min-width
和 max-width
会限制最终的尺寸。而当 flex-direction
为 column
或 column-reverse
的时候,那就是 flex-basis
跟 height
的关系了。
(完)