通过动图形象地为你介绍 flexbox 是如何工作的(二)
作者:Scott Domes
编译:胡子大哈
翻译原文:http://huziketang.com/blog/posts/detail?postId=58acfdc6204d50674934c3aa
英文原文:Even more about how Flexbox works — explained in big, colorful, animated gifs
** 转载请注明出处,保留原文链接以及作者信息**
在上一篇文章中,我们介绍了 flexbox 的几个属性: flex-direction
,justify-content
,align-items
和 align-self
。
这些属性在创建基本布局上是特别有用的。而一旦你开始用 flexbox 创建网站的时候,你需要对其进行深挖以最大化地发挥它的价值。
现在我们来深入探讨一下 flexbox 的缩放,并且学习如何利用它来构建适应性强而且漂亮的布局。
属性1:flex-basis
上一篇文章中,主要介绍了应用在容器上的属性。这次我们专门介绍如何在子元素进行缩放。
首先要介绍的第一个属性在我看来可能是 flexbox 教程里面解释的最少的属性之一。
但是不要担心,其实它很简单。
flex-basis
控制的是一个元素的默认尺寸,但是它可以被flexbox 的其他属性所影响(稍后会详细介绍)。
下面这个 GIF 表示的是它和 width
属性是可以互换的。
然而,flex-basis
和 width
不同的地方是,它是和 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
flex
是 grow
,shrink
和 basis
的简化形式——把它们所有都放到了一起。
它的默认值是: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 属性要讲,请留意随后几周的文章。
我最近正在写一本《React.js 小书》,对 React.js 感兴趣的童鞋,欢迎指点。