flex布局下的flex-grow、flex-shrink、flex-basis属性详解
Flex是Flexible Box的缩写,意为”弹性布局”,用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为Flex布局。
之前学习过flex布局,也可以实现简单的一些布局,例如左侧宽度固定,右侧自适应宽度等。但在实际使用过程中总是会出现一些问题,索性花了一点时间,来好好的总结一下。
1. flex-grow属性
flex-grow
属性定义剩余空间的分成。默认为0,即如果存在剩余空间,也不放大。
.item{
flex-grow: /* default 0 */
}
要了解flex-grow
属性,剩余空间这个概念一定要理解。
先看一个入门的例子,当flex-grow
属性都设置为1时:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
随意改变屏幕的大小,三个div
块的宽度总是相等。
但是,当我们稍微改变一某个span
标签中的内容,三个div
块的宽度便不再相等。
页面内容其实就是三个span
标签中的内容,flex-grow
的逻辑是对剩余空间分成。当前的屏幕宽度为600px
,三个span
标签的长度分别为104px
、104px
、243.4px
,那么页面剩余空间为(600-104-104-243.4)=148.6px
,根据分成的比例1:1:1
(flex-grow
对应的值),可计算得到三个div
标签的分得的剩余空间分别为49.533px
(148.6/3
)、49.533px
、49.533px
,加上标签本来的长度则对应的三个div
的长度分别为153.533px
(104+49.533
)、153.533px
、292.933px
。页面选取对应的div
,长度与计算完全吻合。同样的,如果flex-grow
属性分别为1:1:2
,剩余空间会按照1:1:2
的比例来分成,再加上div
的内容长度,就是其总长度。
下面我们看一个比较经典的布局的例子,部分长度固定,其余长度自适应。
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
除了第三个div
的宽度为200px
外,第一第二个div
对剩余空间1:2
分账。as-flex
对应div
的总长度为600px
,除去固定长度200px
以及第一第二个div
本来占据的宽度104px
(不缩放、也没有剩余空间),屏幕剩余192px
,第一第二个div
按1:2
分配剩余空间,分别分得64px
及128px
。因此第一第二个div
的长度分别为168px
和232px
。
2. flex-shrink属性
flex-shrink属性定义了项目的缩小比例。
flex-shrink
的默认值为1,flex-shrink
的值为0时,不缩放。
.item-1{
flex-shrink: ; /* default 1 */
}
当as-flex
对应的div
的宽度小于其内元素本来宽度之和时,该属性起作用。flex-grow
是对剩余空间进行分配,而flex-shrink
则是对不足空间进行分配。
将上文的html
片段和样式稍作修改
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
在屏幕宽度为300px
时,其显示效果如下图图所示
三个div
标签本来的宽度都为104px
(span
标签的宽度),as-flex
对应的div
的宽度为300px
,很明显,空间不够了,需要大家挤一挤,怎么个挤发,就需要按照flex-shrink
的约定来让出自己的部分空间。例如,三个div
原来都需要占用104px
的空间,总共要占用312px
的空间,现在只有300px
,缺少12px
。按照flex-shrink
的约定,三个div
按照1:1:2
来分配缺少的12px
,三个div
分别让出3px
(12/(1+1+2)
)、3px
、6px
的空间,则最终三个div
的实际长度分别为101px
、101px
、98px
,这与浏览器中div
的实际长度相等。
同样的,如果有一个div
是固定宽度的话,三个div
的宽度如何计算呢?看如下的例子:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9
还是三个div
,前两个div
的flex-shrink
的属性分别为1,2
,也就是说,如果空间不足时,它们按照1:2
让出自己的空间。那么第三个div
在空间不足时,会如何表现呢?设置as-flex
对应的div
的宽度为320px
,在浏览器上选取第三个div
可以发现,虽然我们设置了其长度为208px
,但在宽度不足时,其也随之缩小(165.633px
)。由此可见,虽然我们没有设置第三个div
的flex-shrink
属性,但其也是按一定的比例出让的自己的空间,否则第三个div
的宽度不应该缩小。
具体按什么比例出让,将as-flex
对应的div
的宽度设置成320px
,修改第三个div
的flex-shrink
属性,得到下表:
属性 | div1出让宽度 | div2出让宽度 | div3出让宽度 | 出让比例 |
---|---|---|---|---|
1:2:(208px) | 19.2 | 38.4 | 38.4 | 1:2:2 |
1:2:(0,208px) | 32 | 64 | 208 | 1:2:0 |
1:2:(1,208px) | 19.2 | 38.4 | 38.4 | 1:2:2 |
1:2:(2,208px) | 90.2833 | 76.5667 | 153.15 | 1:2:4 |
1:2:(3,208px) | 93.3333 | 82.6667 | 144 | 1:2:6 |
注 1. 三个div
分别命名为div1
、div2
、div3
。2. 属性1:2:(1,208px)
表示div1
和div2
的flex-shrink
的属性分别为1和2,div3
的flex-shrink
属性为1,width
属性为208px
。3.div1
和div2
的出让宽度为本来宽度(104px
)减去当前实际宽度,div3
的出让宽度为本来宽度(208px
)减去当前实际宽度。4. 由于四舍五入的原因,第三第四行的出让比例为约等于,但是比例非常的接近。
由上表得出的结论为,项目的实际出让比例 = flex-shrink
比例 * 实际宽度比例。例如上述例子中,项目的实际宽度比为1:1:2
(104:104:208
),flex-shrink
属性的比例为1:2:2
,则实际出让比例为1:2:4
。
3. flex-basis属性
flex-basis属性定义了项目占据的主轴空间。浏览器根据这个属性,计算主轴多余空间或不足空间的大小。它的默认值为auto,即项目的本来大小。
.item {
flex-basis: | auto; /* default auto */
}
上文中,我们使用的div
标签的本来宽度为104px
,这是浏览器自己计算出来的,而flex-basis
可以帮助开发者人为的指定项目的宽度,以便于浏览器计算剩余空间或者不足空间。举个例子:
1 2 3 4 5 6 7 8 9
1 2 3 4 5 6 7 8 9 1 2 3 4 5
1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9
页面显示效果如下图所示,显然屏幕宽度足够,有剩余空间,三个div
按照1:1:1
平分剩余空间,但是由于,项目本来长度的不同,因此三个div
的实际长度必不相同。
此时项目的本来长度是浏览器根据内容自己计算出来的。利用flex-basis
属性,我们可以指定项目本来长度,在上面代码的基础上,我们分别为三个div
添加flex-basis-100
类,指定三个div
的本来长度为100px
,则显示效果如下图所示:
三个div
的实际长度均为200px
,这是由于对于多余的空间(600-100*3
),三个div
均分都为100px
,而项目原始长度都为100px
,因此项目的实际长度都为200px
。同样的道理,as-flex
对应的div
宽度为240px
时,空间不足,缺少60px
,按照空间不足时的宽度出让规则,每个div
分别出让20px
的空间,所以其实际长度为80px
。
项目的原始长度由flex-basis
和width
属性控制。flex-basis
的优先级高于width
属性,如果只设置了width
属性,flex-basis
为auto
,则项目的原始长度等于width
,而如果同时设置了width
和flex-basis
,则项目的原始长度等于flex-basis
。因此上文中用到width
的地方可以使用flex-basis
来代替。
注意:
- 即便在相同代码的情况下,可能会由于浏览器的原因,产生标签长度与文中不一致的地方。
- 本来宽度是值,当
div
为此宽度时,没有空间没有剩余也没有不足。 - 文章采用的浏览器为
Firefox 61.0.1 (64 位)
。
文章到此结束,如有错误,请各位道友不吝赐教。