元素如何弹性伸缩应对

flex-warp:nowrap;不换行时,容器宽度有剩余/不够分,弹性元素们该怎么“弹性”地伸缩应对?
这里针对上面两种场景,引入两个属性:
flex-shrink:缩小比例(容器宽度元素总宽度时如何伸展)

1.flex-shrink:缩小比例

接下来我们看一个场景,弹性容器#container的宽度是200px,它里面有三个弹性元素,宽度分别是50px、100px、120px。在不换行的情况下,此时容器宽度明显是不够的。

<div class="container">
    <div class="box1"></div>
    <div class="box2"></div>
    <div class="box3"></div>
</div>

实际上,flex-shrink默认为1,也就是当不够分配时,元素都将等比例缩小,占满整个宽度,如下图。

元素收缩的计算方法

1.弹性元素1:50px→37.03px
2.弹性元素2:100px→74.08px
3.弹性元素3:120px→88.89px
先抛结论:flex-shrink:1并非严格等比缩小,它还会考虑弹性元素本身的大小
– 容器剩余宽度:-70px
– 缩小因子的分母:1*50 + 1*100 + 1*120 = 270 (1为各元素flex-shrink的值)
– 弹性元素1的缩小因子:1*50/270
– 弹性元素1的缩小宽度为缩小因子乘于容器剩余宽度:1*50/270 * (-70)
– 弹性元素1最后则缩小为:50px + (1*50/270 *(-70)) = 37.03px
这里加入弹性元素本身大小作为计算方法的考虑因素,主要是为了避免将一些本身宽度较小的元素在收缩之后宽度变为0的情况出现

2.flex-grow:放大比例

同样,弹性容器#container的宽度是200px,但此时它里面只有两个弹性元素,宽度分别是50px、100px。此时容器宽度是有剩余的。这里flex-grow决定了要不要分配以及各自分配多少。
(1)在flex布局中,容器剩余宽度默认是不进行分配的,也就是所有弹性元素的flex-grow都为0。

(2)通过指定flex-grow为大于0的值,实现容器剩余宽度的分配比例设置

元素放大的计算方法

放大的计算方法与缩小不一样,没有将元素大小纳入考虑。
只按flex-grow声明的份数算出每个需分配多少,叠加到原来的尺寸上。
– 容器剩余宽度:50px
– 分成每份:50px / (3+2) = 10px
– 弹性元素1放大为:50px + 3 * 10 = 80px

注意,无多余宽度时,flex-grow无效
同理,对于flex-shrink,在容器宽度有剩余时也是不会生效的。因此这两个属性是针对两种不同场景的互斥属性。

弹性处理与刚性尺寸

在进行弹性处理之余,其实有些场景我们更希望元素尺寸固定,不需要进行弹性调整。设置元素尺寸除了width和height以外,flex还提供了一个flex-basis属性。
flex-basis设置的是元素在主轴上的初始尺寸,所谓的初始尺寸就是元素在flex-growflex-shrink生效前的尺寸。

1.与width/height的区别

首先以width为例进行比较。看看下面的例子。

<div class="container">
    <div class="box1">盒子1</div>
    <div class="box2">盒子2</div>
</div>
body {
    background-color: #5b7a97;
}
.container {
    width: 200px;
    display: flex;
    background-color: #80c59c;
    padding: 50px;
    color: white;
}
.container > div {
    background-color: #60b683;
}
(1) 两者都为0
div.box1 {
    width: 0;
}
div.box2 {
    flex-basis: 0;
}


– width:0 完全没有显示
– flex-basis:0 根据内容撑开宽度

(2) 两者非0
div.box1 {
    width: 50px;
    background-color: #b6497b;
}
div.box2 {
    flex-basis: 50px;
}


– width: 非0;
– flex-basis: 非0
– 数值相同时两者等效

(3)两者非0并且同时设置
div.box1 {
    width: 50px;
    background-color: #b6497b;
}
div.box2 {
    flex-basis: 50px;
    width: 60px;
}


– width: 非0;
– flex-basis: 非0
– 同时设置,flex-basis优先级高

(4)flex-basis为auto
div.box1 {
    background-color: #b6497b;
    flex-basis: auto;
}
div.box2 {
    flex-basis: auto;
    width: 60px;
}


– flex-basis为auto时,如设置了width则元素尺寸由width决定;没有设置则由内容决定

(5)flex-basis 等于 主轴上的尺寸 不等于 width
.container {
    width: 200px;
    display: flex;
    background-color: #80c59c;
    padding: 50px;
    color: white;
    flex-direction: column;
}
.container > div {
    background-color: #60b683;
}
div.box1 {
    background-color: #b6497b;
    flex-basis: auto;
    height: 50px;
}
div.box2 {
    flex-basis: 60px;
    width: 100px;
}


– 将主轴方向改为:上→下
– 此时主轴上的尺寸是元素的height
– flex-basis 等于 height

2.常用的复合属性 flex

这个属性应该是最容易迷糊的一个,下面揭开它的真面目。
flex = flex-grow + flex-shrink + flex-basis
复合属性,前面说的三个属性的简写。
flex:2 1 100px表示同时设置:flex-grow:2flex-shrink:1flex-basis:100px
一些简写方式:
flex:1 = flex:1 1 0%
flex:2 = flex:2 1 0%
flex: auto = flex: 1 1 auto
flex: none = flex: 0 0 auto 该方式常用于固定尺寸 不伸缩

flex:1和flex:auto的区别

其实可以归结于flex-basis:0flex-basis:auto的区别。
flex-basis是指定初始尺寸,当设置为0时(绝对弹性元素),此时相当于告诉flex-growflex-shrink在伸缩的时候不需要考虑我的尺寸;相反当设置为auto时(相对弹性元素),此时则需要在伸缩时将元素尺寸纳入考虑。
因此从下图可以看到绝对弹性元素如果flex-grow值是一样的话,那么他们的尺寸一定是一样的。

Leave a Comment