通过动图形象地为你介绍 Flexbox 是如何工作的(二)

1,080 阅读7分钟
原文链接: huzidaha.com

作者:Scott Domes
编译:胡子大哈

翻译原文:huzidaha.com/posts/detai…
英文原文:medium.freecodecamp.com/even-more-a…

转载请注明出处,保留原文链接以及作者信息


上一篇文章中,我们介绍了 flexbox 的几个属性: flex-directionjustify-contentalign-itemsalign-self

这些属性在创建基本布局上是特别有用的。而一旦你开始用 flexbox 创建网站的时候,你需要对其进行深挖以最大化地发挥它的价值。

现在我们来深入探讨一下 flexbox 的缩放,并且学习如何利用它来构建适应性强而且漂亮的布局。

属性1:flex-basis

上一篇文章中,主要介绍了应用在容器上的属性。这次我们专门介绍如何在子元素进行缩放。

首先要介绍的第一个属性在我看来可能是 flexbox 教程里面解释的最少的属性之一。

但是不要担心,其实它很简单。

flex-basis 控制的是一个元素的默认尺寸,但是它可以被flexbox 的其他属性所影响(稍后会详细介绍)。

下面这个 GIF 表示的是它和 width 属性是可以互换的。

然而,flex-basiswidth 不同的地方是,它是和 flex 坐标轴保持一致的。

flex-basis 是在主轴方向上影响元素大小的。

我们来看一下,当保持 flex-basis 不变的情况下,改变主轴方向,会发生什么。

这里要注意,原来设置的是 height 属性,现在必须要手动地设置 width 属性。flex-basis 根据 flex-direction 的不同会影响到 width 或者 height

属性2:flex grow

接下来会有点复杂。

首先,把所有的方块 width 都设置为120px:

现在来介绍一个属性 flex-grow,它的默认值是 0。意味着这些方块不允许自动填充剩下的空间。

这又是什么意思呢?让我们来看看,如果把各个方块的 flex-grow 设置成 1 会发生什么:

所有方块一起充满了整个容器的宽度,并且它们之间的间隙也都是相同的,说明 flex-grow 覆盖了 width

关于 flex-grow 让人疑惑的地方在于它的值具体表达什么意思呢?flex-grow: 1 意味着什么呢?

为了解释这个问题,我们把每个方块的 flex-grow 值设置成 999,看一下效果:

可以看到,并没有变化。

这是因为:flex-grow 并不是一个绝对值,而是一个相对值。

对于每个方块来说,重要的不是 flex-grow 的值是多大,而是它的这个值和其他方块的这个值相比较,相对大小是怎么样的

如果设置每个方块为 flex-grow: 1,然后逐渐改变第三个方块的 flex-grow,可以看到下图的改变:

为了完全理解这个知识点,我们来快速简单地来计算一下。

每个方块 flex-grow 的起始值都是 1。把所有方块的该值加起来,总和是 6。因此容器的总宽度被分成了 6 份。每个方块就被扩展到容器所有可用空间的 1/6

然后设置第三个方块的 flex-grow 值为 2。那么容器的宽度被分成 7 等份,因为所有 flex-grow 属性是:1 + 1 + 2 + 1 + 1 + 1。

第三个方块占了整个容器空间的 2/7,其他的占了 1/7。

同理,当设置第三个方块的 flex-grow: 3 的时候,整个容器宽度被分成了 8 份(1 + 1 + 3 + 1 + 1 + 1),第三个方块占了 3/8,其他的占了 1/8。

以此类推。

flex-grow 只和比例相关,例如,设置第三个方块 flex-grow: 12,其余每个方块的 flex-grow: 4;跟第三个设置成 3,其他的设置成 1 得到同样的效果,见下图:

重点在于,每个方块的 flex-grow 和其他方块的是成比例的

最后要注意的是,和 flex-basis 一样,flex-grow 也是应用在主轴上的。除非把 flex-direction 设置为 column,否则 flex-grow 只会影响方块的宽度。

属性3:flex shrink

flex-shrink 刚好和 flex-grow 相反,它是决定方块收缩多少的。

它只应用于元素必须要缩小以适应容器的情况,即容器太小了。

它的主要用法是指定哪个元素你想要缩小,哪个不想缩小。默认情况是每个方块都 flex-shrink: 1,这表示每个方块都会随着容器的缩小而缩小。

我们来实战中体会一下,在下面的 GIF 图中,每个方块的 flex-grow 都是 1,所以它们填满了整个容器。每个方块的 flex-shrink 也都是 1,所以它们也会像下面图中这样收缩。

接下来我们来设置第三个方块的 flex-shrink 值为 0。不允许它收缩,所以它会随着容器拉伸而拉伸,但是当容器收缩的时候,却不允许比它的 120px 的width 还小。

flex-shrink 的默认值是 1,说明除非你特定地去设定这个值,否则元素都是默认收缩的。

同样,flex-shrink 是和比例相关的。如果设置一个方块的 flex-shrink 为 6,而其他的是 2,那么这个方块随着容器空间的压缩,将以 3 倍于其他方块的速度缩小。

这里尤其注意:是收缩的速度是 3 倍,而不是说它的宽度会缩小到原来的 1/3

接下来准备更深入探讨元素是如何收缩和拉伸的。不过在这之前,还需要介绍最后一个属性,把这些东西都串起来。

属性4:flex

flexgrowshrinkbasis 的简化形式——把它们所有都放到了一起。

它的默认值是:0(grow),1(shrink)和 auto(basis)。

我们把上一个例子简化成只有两个方块,下面是它们的属性:

.square#one {
  flex: 2 1 300px;
}
.square#two {
  flex: 1 2 300px;
}

两个方块都有着相同的 flex-basis。也就是说如果有足够的空间(容器的空间等于 600px 加上 margin 和 padding),它们的宽度将都会是 300px。

但是随着容器的拉伸,方块 1(有更大的 flex-grow 值)将会以两倍的速度增长。随着容器的收缩,方块 2 (有更大的 flex-shrink 值)将会以两倍的速度收缩。

都放到一起展示,如下图:

元素是怎样收缩和拉伸的呢

有些人可能会疑惑地发现:当方块 1 拉伸时,并没有拉伸到方块 2 的两倍大小。同样,当方块 2 缩小时,也并没有缩小到方块 1 的一半,尽管 flex-shrink 的比值是 2:1。

实际上这两个属性的意思,并不是说它们的大小是 2:1 或者 1:2,而是说它们的收缩率或拉伸率

来点简单的计算

容器的初始大小是 640px。在除去容器要预留的 20px 的 padding 后,剩下的空间足够让两个方块满足 flex-basis 等于 300px。

当把容器设置为 430px 时,空间减小了 210px。方块 1,设置了 flex-shrink 是 1,减小了 70px。而方块 2,设置了 flex-shrink 是 2,减小了 140px。

当容器缩小到了 340px,容器空间减小了 300px。这时方块 1 减小 100px,而方块 2 减小 200px。

整体减小空间的分配方式,是按照各自设置的 flex-shrink 比例分配的(2:1)。

对于 flex-grow 也一样。当容器拉伸到 940px 时,整体增加了 300px,方块 1 增加 200px,而方块 2 增加 100px。

当涉及到 flex 属性时,其实它们说的都是比例

从上图中,可以看到宽度是如何根据设置的比例变化的,其中的 delta (∆) 表示和原始 flex-basis 相比的变化量。

结论

最后总结一下:flex-basis 指的是一个元素在发生缩放之前,沿着主轴方向的大小。flex-grow 指的是在元素拉伸时,和兄弟元素相比的拉伸比例。flex-shrink 指的是在元素收缩时,和兄弟元素相比的收缩比例。

我们还有几个 flexbox 属性要讲,请留意随后几周的文章。

胡子大哈悟以往之不谏,知来者之可追