CSS:深入理解flex: <‘flex-grow‘> <‘flex-shrink‘> <‘flex-basis‘>;

说明:本文flex-direction默认是row,且不再介绍flex基础知识。若想学习基础语法,可参阅阮一峰老师的博文Flex 布局教程:语法篇

一:flex-basis 和 width之争,flex-basis完胜

结论:当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了height) , flex-basis 具有更高的优先级。

即:一个元素同时设置了flex-basis(除值为 auto 外) 和 width,width失效。

栗子1:flex-basis不为auto

<!--html-->
<div class="flex_box">
    <div class="flex-item_left">Item One</div>
    <div class="flex-item_middle">Item Two</div>
</div>


<style>
    /*css*/
    .flex_box {
        display: flex;
        flex-direction: row;
        background-color: #fff;
        width: 320px;
        height: 40px;
        margin: 0 auto;
    }
    .flex-item_left {
        width: 100px;
        flex-basis: 80px;
        background-color: #fb3;
    }
    .flex-item_middle {
        flex-basis: 80px;
        width: 100px;
        background-color: #96AD91;
    }
</style>

 浏览器效果:

0d9cc3f8219149a6b5e635950de4af73.png

Item One和Item Two同时定义了width: 100px;和 flex-basis: 80px,只是顺序有差异。

结果:在css中,无论with和flex-basis谁先定义,最后生效的总是 flex-basis。

栗子2:flex-basis为auto

<!--html-->
<div class="flex_box">
    <div class="flex-item_left">Item One</div>
    <div class="flex-item_middle">Item Two</div>
</div>


<style>
    /*css*/
    .flex_box {
        display: flex;
        flex-direction: row;
        background-color: #fff;
        width: 320px;
        height: 40px;
        margin: 0 auto;
    }
    .flex-item_left {
        width: 100px;
        flex-basis: auto;
        background-color: #fb3;
    }
    .flex-item_middle {
        flex-basis: auto;
        width: 100px;
        background-color: #96AD91;
    }
</style>

本例中,仅将栗子1中flex-basis的值改为auto

浏览器效果:

2ba0e5e63f31451bb004933558a240f0.png

这里说明了,flex-basis优先级高的条件是,值不能为auto。

二:flex简写

flex属性是 flex-grow,flex-shrink 和 flex-basis的简写,默认值为0 1 auto。

有些属性可选,被省略后会被自动补全。

分类简写实际的值说明
<flex-grow>flex: 1;flex: 1 1 0%;

<flex-grow>

1/0 是<flex-grow> 值,此时简写会扩展为:
flex: <flex-grow> 1 0%;

flex: 0;flex: 0 1 0%;
<flex-basis>flex: 100px;flex: 1 1 100px;

<flex-basis>

100px / auto 是<flex-basis> 值,此时简写会扩展为:
flex: 1 1 <flex-basis>;

flex: auto;flex: 1 1 auto;
flex: initial;flex: 0 1 auto;能屈不能伸
flex: none;flex: 0 0 auto;

注意区分none和0。

它俩本质并不相同。

双值语法flex: 1 1;flex: 1 1 0%;

双值语法

第一个值只能是<flex-grow>,

第二个值可能是<flex-shrink>或<flex-basis>

  <flex-shrink>会扩展为:

  flex: <flex-grow> <flex-shrink> 0%

  <flex-basis>会扩展为:

  flex: <flex-grow> 1 <flex-basis>

flex: 1 100px;flex: 1 1 100px;

关于简写的值,上述表格并未全部列出。但应对平时的开发足矣。

三:flex-grow原理

这个属性规定了 flex-grow 项在 flex 容器中分配剩余空间的相对比例。

  • 它的数据类型为number,取值范围为[0, +∞)
  • 默认为0,即如果存在剩余空间,也不放大。
  • 实际分配空间=剩余分配空间*MIN(1, Sum(flex-grow))
  • 它是对剩余空间的相对占比,而不是当前元素在flex容器中的占比。
  • 所有子元素的flex-basis都为0,flex-grow就是子元素在flex容器中的占比
  • flex-basis: auto元素 参与分配(不考虑width的影响)

栗子3 - Sum(flex-grow)≥1

每个子元素都是 flex: <flex-grow>;

<div class="flex-grow_box">
    <div class="flex-grow-item_a">A</div>
    <div class="flex-grow-item_b">B</div>
    <div class="flex-grow-item_c">C</div>
    <div class="flex-grow-item_d">D</div>
    <div class="flex-grow-item_e">E</div>
</div>

<style>
    .flex-grow_box {
        display: flex;
        flex-direction: row;
        background-color: #fff;
        width: 400px;
        height: 40px;
        margin: 0 auto;
    }
    .flex-grow-item_a {
        flex: 1;
        background-color: #1F4642;
    }
    .flex-grow-item_b {
        flex: 1;
        background-color: #96AD91;
    }
    .flex-grow-item_c {
        flex: 1;
        background-color: #58a;
    }
    .flex-grow-item_d {
        flex: 2;
        background-color: #fb3;
    }
    .flex-grow-item_e {
        flex: 3;
        background-color: #564D38;
    }
</style>

浏览器效果:

313751406a5a4eb5a7362efd4155f856.png

  • 每个子元素貌似是按照1:1:1:2:3的比例分配的,是因为每个子元素的flex-basis是0%。
  • box总宽是400px,每个子元素占宽0(flex-basis是0%),剩余分配空间是400px。
  • 每个子元素按照flex-grow(1:1:1:2:3)分配400px

特例:如果box只有两个子元素,且每个子元素flex: 1; 那这俩子元素宽度1:1等分。

栗子3也说明一点,如果flex所有子元素的flex-basis都是0,flex-grow就是当前元素在flex容器中的占比。

栗子4 - Sum(flex-grow)<1

每个子元素都是 flex: <flex-grow>;

<div class="flex-grow_box">
    <div class="flex-grow-item_a">A</div>
    <div class="flex-grow-item_b">B</div>
    <div class="flex-grow-item_c">C</div>
    <div class="flex-grow-item_d">D</div>
    <div class="flex-grow-item_e">E</div>
</div>

<style>
    .flex-grow_box {
        display: flex;
        flex-direction: row;
        background-color: #fff;
        width: 400px;
        height: 40px;
        margin: 0 auto;
    }
    .flex-grow-item_a {
        flex: 0.1;
        background-color: #1F4642;
    }
    .flex-grow-item_b {
        flex: 0.1;
        background-color: #96AD91;
    }
    .flex-grow-item_c {
        flex: 0.1;
        background-color: #58a;
    }
    .flex-grow-item_d {
        flex: 0.2;
        background-color: #fb3;
    }
    .flex-grow-item_e {
        flex: 0.3;
        background-color: #564D38;
    }
</style>

浏览器效果: 

栗子4,是栗子3中将所有的flex-grow的值除以10的效果。

  • box总宽是400px,每个子元素占宽0(flex-basis是0%),剩余分配空间是400px。
  • 每个子元素按照flex-grow(1:1:1:2:3)分配320px
    实际分配空间 = 剩余分配空间 *  Sum(flex-grow)
  • 栗子3中,Sum(flex-grow) = 8,可实际分配空间对应的系数是1。
    实际分配空间 = 剩余分配空间 * 1
  • 可以理解成地主家也没有余粮(最多1),几个S儿子要财产,多了没有(≤1),少了就给自己留点(Sum(flex-grow))。
     
  • 总结一下这个公式:
    实际分配空间=剩余分配空间*MIN(1, Sum(flex-grow))

这时如果有个Q1,剩余空间都会被占用吗?答:不会。这里需要考虑Sum(flex-grow) 是不是大于1。

栗子5 - 正常分配剩余空间

<div class="flex-grow_box">
    <div class="flex-grow-item_a">A</div>
    <div class="flex-grow-item_b">B</div>
    <div class="flex-grow-item_c">C</div>
    <div class="flex-grow-item_d">D</div>
    <div class="flex-grow-item_e">E</div>
</div>

.flex-grow_box {
    display: flex;
    flex-direction: row;
    background-color: #fff;
    width: 400px;
    height: 40px;
    margin: 0 auto;
}
.flex-grow-item_a {
    flex: 1 0 40px;
    background-color: #1F4642;
}
.flex-grow-item_b {
    flex: 1 0 80px;
    background-color: #96AD91;
}
.flex-grow-item_c {
    flex: 2 0 40px;
    background-color: #58a;
}
.flex-grow-item_d {
    flex: 2 0 80px;
    background-color: #fb3;
}
.flex-grow-item_e {
    flex: 4 0 40px;
    background-color: #564D38;
}

浏览器效果: 

 

  • 子元素的flex-basis--,合计占宽(sum=280px)
    小于box宽,存在剩余空间(本例中=400-sum=120px)
  • 子元素的flex-grow合计是10,
    实际分配空间=剩余分配空间*MIN(1, Sum(flex-grow)) = 120 * 1 = 120px。
  • 子元素按照flex-grow(1:1:2:2:4)分配120px,得到分配空间--
  • 实际宽度③ = ① + ②

 栗子5也说明了flex-grow是对剩余空间的相对占比,而不是当前元素在flex容器中的占比。

栗子6 - flex-basis: auto元素 参与分配

<div class="flex-grow_box">
    <div class="flex-grow-item_a">A</div>
    <div class="flex-grow-item_b">B</div>
    <div class="flex-grow-item_c">C</div>
</div>

.flex-grow_box {
    display: flex;
    flex-direction: row;
    background-color: #fff;
    width: 400px;
    height: 40px;
    margin: 0 auto;
}
.flex-grow-item_a {
    flex: 1 0 100px;
    background-color: #1F4642;
}
.flex-grow-item_b {
    flex: 2 0 auto;
    background-color: #96AD91;
}
.flex-grow-item_c {
    flex: 3 0 100px;
    background-color: #58a;
}

浏览器效果: 

  • 子元素的flex-basis/auto--,合计占宽(sum=200px + 10.04(子元素B))
    小于box宽,存在剩余空间(本例中=400-sum=189.96px)
  • 子元素的flex-grow合计是6,
    实际分配空间=剩余分配空间*MIN(1, Sum(flex-grow)) = 189.96 * 1 = 189.96px。
  • 子元素按照flex-grow(1:2:3)分配 189.96 px,得到分配空间--
  • 实际宽度③ = ① + ②

重点说明,flex-basis为auto时,这里未将width考虑在内。实际宽度公式并未考虑width的情况,如果有小可爱提出本文公式有问题,这里不做解释。

四:flex-shrink原理

这个属性指定了 flex 元素的收缩规则

  • 它的数据类型为number,取值范围为[0, +∞),默认为1
  • flex 元素仅在默认宽度之和大于容器的时候才会发生收缩
  • 实际收缩空间=需要收缩空间*MIN(1, Sum(flex-shrink))
  • 实际收缩比例,受 (flex-shrink*flex-basis) 的影响--这点和flex-grow重点区分
  • flex-basis: auto的子元素,不设置width,不参与收缩--这点和flex-grow重点区分
    flex-basis: auto的子元素,设置width,正常收缩

栗子7 - Sum(flex-shrink)≥1

<div class="flex-shrink_box">
    <div class="flex-shrink-item_a">A</div>
    <div class="flex-shrink-item_b">B</div>
    <div class="flex-shrink-item_c">C</div>
</div>

.flex-shrink_box {
    display: flex;
    flex-direction: row;
    background-color: #fff;
    width: 400px;
    height: 40px;
    margin: 0 auto;
}
.flex-shrink-item_a {
    flex: 1 1 100px;
    background-color: #1F4642;
}
.flex-shrink-item_b {
    flex: 1 2 200px;
    background-color: #96AD91;
}
.flex-shrink-item_c {
    flex: 1 3 300px;
    background-color: #58a;
}

浏览器效果: 

  • 子元素的flex-basis--,合计占宽(sum=600px)
    大于box宽,空间不足需收缩(本例中=400-sum=-200px)
  • 子元素的flex-shrink合计是6,
    实际收缩空间=需要收缩空间*MIN(1, Sum(flex-shrink)) = 200 * 1 = 200px。
  • 子元素按照(flex-shrink*flex-basis) 进行收缩:
    按照1*100 : 2*200 : 3*300=1:4:9 收缩200px,得到收缩空间--
    A:200 * 1 / 14 = 14.29  // 保留两位小数 
    B:200 * 4 / 14 =  57.14 // 和浏览器有0.01px的精度差
    C:200 * 9 / 14 = 128.57
  • 实际宽度③ = ① - ②

栗子8 - Sum(flex-shrink)<1

<div class="flex-shrink_box">
    <div class="flex-shrink-item_a">A</div>
    <div class="flex-shrink-item_b">B</div>
    <div class="flex-shrink-item_c">C</div>
</div>

.flex-shrink_box {
    display: flex;
    flex-direction: row;
    background-color: #fff;
    width: 400px;
    height: 40px;
    margin: 0 auto;
}
.flex-shrink-item_a {
    flex: 1 0.1 100px;
    background-color: #1F4642;
}
.flex-shrink-item_b {
    flex: 1 0.2 200px;
    background-color: #96AD91;
}
.flex-shrink-item_c {
    flex: 1 0.3 300px;
    background-color: #58a;
}

 浏览器效果: 

  • 子元素的flex-basis--,合计占宽(sum=600px)
    大于box宽,空间不足需收缩(本例中=400-sum=-200px)
  • 子元素的flex-shrink合计是0.6,
    实际收缩空间=需要收缩空间*MIN(1, Sum(flex-shrink)) = 200 * 0.6 = 120px
  • 子元素按照(flex-shrink*flex-basis) 进行收缩:
    按照0.1*100 : 0.2*200 : 0.3*300= 1:4:9 收缩200px,得到收缩空间--
    A:120 * 1 / 14 = 8.57 // 保留两位小数 
    B:120 * 4 / 14 = 34.29 // 和浏览器有0.01px的精度差
    C:120 * 9 / 14 = 77.14
  • 实际宽度③ = ① - ②

栗子9 - flex-basis: auto元素,不参与收缩(不设置width)

<div class="flex-shrink_box">
    <div class="flex-shrink-item_a">A</div>
    <div class="flex-shrink-item_b">B</div>
    <div class="flex-shrink-item_c">C</div>
</div>

.flex-shrink_box {
    display: flex;
    flex-direction: row;
    background-color: #fff;
    width: 400px;
    height: 40px;
    margin: 0 auto;
}
.flex-shrink-item_a {
    flex: 1 0.4 200px;
    background-color: #1F4642;
}
.flex-shrink-item_b {
    flex: 1 0.2 auto;
    background-color: #96AD91;
}
.flex-shrink-item_c {
    flex: 1 0.5 300px;
    background-color: #58a;
}

 浏览器效果: 

  • 子元素的flex-basis/auto--,合计占宽(sum=500px + 10.04(子元素B))
    大于box宽,空间不足需收缩(本例中=400-sum=-110.04px)
  • 子元素的flex-shrink合计是0.9(不含auto),
    实际收缩空间=需要收缩空间*MIN(1, Sum(flex-shrink)) = 110.04 * 0.9 = 99.036px
  • 子元素按照(flex-shrink*flex-basis) 进行收缩:
    按照0.4*200  : 0.5*300 = 8 : 15 收缩 99.036px,得到收缩空间--
    A:99.036 * 8 / 23 = 34.45 // 保留两位小数 -- 和浏览器有0.01px的精度差
    B:auto 不参与收缩
    C:99.036 * 15 / 23 = 64.59
  • 实际宽度③ = ① - ②

无实例说明:flex-basis: auto元素,设置了width。将width代入flex-basis,正常收缩。

五:flex-basis、min-width、max-width之争

默认情况下,元素不会缩短至小于内容框尺寸,若想改变这一状况,请设置元素的min-width 与 min-height属性。

栗子10

<div class="flex_box">
    <div class="flex-item_a1">A1</div>
    <div class="flex-item_a2">A2</div>
    <div class="flex-item_b1">B1</div>
    <div class="flex-item_b2">B2</div>
    <div class="flex-item_c1">C1</div>
    <div class="flex-item_c2">C2</div>
    <div class="flex-item_c3">C3</div>
    <div class="flex-item_d1">D1</div>
    <div class="flex-item_d2">D2</div>
    <div class="flex-item_e1">E1</div>
    <div class="flex-item_e2">E2</div>
    <div class="flex-item_e3">E3</div>
</div>

<style>
    .flex_box {
        display: flex;
        flex-direction: row;
        background-color: #fff;
        height: 40px;
        margin: 0 auto;
        color: #fff;
    }

    .flex-item_a1 {
        min-width: 30px;
        flex: 0 0 40px;
        background-color: #1F4642;
    }

    .flex-item_a2 {
        min-width: 50px;
        flex: 0 0 40px;
        background-color: #96AD91;
    }

    .flex-item_b1 {
        flex: 0 0 40px;
        max-width: 30px;
        background-color: #1F4642;
    }

    .flex-item_b2 {
        flex: 0 0 40px;
        max-width: 50px;
        background-color: #96AD91;
    }

    .flex-item_c1 {
        min-width: 30px;
        max-width: 50px;
        flex: 0 0 20px;
        background-color: #1F4642;
    }

    .flex-item_c2 {
        min-width: 30px;
        max-width: 50px;
        flex: 0 0 40px;
        background-color: #96AD91;
    }

    .flex-item_c3 {
        min-width: 30px;
        max-width: 50px;
        flex: 0 0 60px;
        background-color: #58a;
    }

    .flex-item_d1 {
        min-width: 40px;
        max-width: 40px;
        flex: 0 0 30px;
        background-color: #1F4642;
    }

    .flex-item_d2 {
        min-width: 40px;
        max-width: 40px;
        flex: 0 0 50px;
        background-color: #96AD91;
    }

    .flex-item_e1 {
        min-width: 40px;
        max-width: 30px;
        flex: 0 0 20px;
        background-color: #1F4642;
    }

    .flex-item_e2 {
        min-width: 40px;
        max-width: 30px;
        flex: 0 0 35px;
        background-color: #96AD91;
    }

    .flex-item_e3 {
        min-width: 40px;
        max-width: 30px;
        flex: 0 0 50px;
        background-color: #58a;
    }
</style>

浏览器效果: 

3d33c3f5396e4f4685aff5b9b9f96a68.png

设置不同的值,来总结规律:

  • 只有min-width和flex-basis,实际宽度 = MAX(min-width, flex-basis)
  • 只有max-width和flex-basis,实际宽度 =  MIN(max-width, flex-basis)
  • 同时有min-width、max-width、flex-basis
  1. min-width < max-width,实际宽度取值范围 [min-width, max-width] 
    flex-basis < max-width:实际宽度 = MAX(min-width, flex-basis)
    flex-basis ≥ max-width:实际宽度 = MIM(max-width, flex-basis)
  2. min-width ≥ max-width,实际宽度 = min-width

所以在写CSS代码时,使用flex-basis时,谨慎使用max-width和min-width。

六:flex: 1; 两栏布局

使用场景,两栏布局:左边宽度固定,右边宽度自适应

<div class="box">
    <div class="left"></div>
    <div class="right"></div>
</div>

/*css*/
.box {
    display: flex;
    height: 100px;
}
.left {
    /*下面三行代码,任选一行*/
    width: 100px;
    /*flex: 0 0 100px;*/
    /*flex: 0 1 100px;*/
    background-color: #1F4642;
}
.right {
    flex: 1;
    background-color: #96AD91;
}
  •    .left:
    1)只设定了width,flex就是initial; (即:flex: 0 1 auto)。能屈不能伸。
    2)如果不设置width,设置flex:0 0 100px; 或 0 1 100px; 都阔以。
    所谓宽度固定,就是通过width或者flex-basis定宽,且flex-grow为0。
  • .right:设置了flex: 1(即:flex: 1 1 0%)。能屈能伸。
  • .box宽大于100px时,超出100px的部分都是.right的,也就是所谓的自适应布局。

原理并不复杂,实现也很简单。

七:flex: auto;

谈flex: auto; , 本质是讨论元素flex-basis值为auto的情况。

元素设置了flex-basis: auto后,元素会根据自身宽高来确定尺寸,就是靠内容撑起自身。

The End.

  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CSS3中,flexbox布局是一种非常强大的布局方式,可以通过一些属性来实现弹性伸缩和对齐。其中,flex-growflex-shrinkflex-basis就是控制弹性伸缩的重要属性。 flex-grow 属性 flex-grow 属性用于指定元素在弹性容器中的伸展比率,即当元素所在容器有剩余空间时,元素按照比例分配剩余空间。默认值为 0,即当剩余空间不足时,元素不会伸展。 例如,当一个容器中有两个元素,一个 flex-grow 值为 1,另一个为 2,则第二个元素在容器有剩余空间时会比第一个元素多分配一倍的剩余空间。 flex-shrink 属性 flex-shrink 属性用于指定元素在弹性容器中的收缩比率,即当元素所在容器空间不足时,元素按照比例收缩。默认值为 1,即元素会自动收缩。 例如,当一个容器中有两个元素,一个 flex-shrink 值为 1,另一个为 2,则第二个元素在容器空间不足时会比第一个元素多收缩一倍。 非常重要的一点是,如果所有元素的 flex-shrink 属性值都为 0,则它们不会收缩。 flex-basis 属性 flex-basis 属性用于指定元素在弹性容器中的基准值,即元素在不伸展或收缩的情况下所占据的空间。默认值为 auto,即元素的大小由其本身的大小决定。 例如,当一个容器中有两个元素,一个 flex-basis 值为 100px,另一个为 200px,则第一个元素在不伸展或收缩的情况下会占据 100px 的空间。 综合运用 这三个属性通常一起使用,例如: flex: 1 0 auto; 这个属性的意思是元素在弹性容器中会按照 flex-grow 属性的比例伸展,但不会收缩,基准值由 flex-basis 决定。 总结 flex-growflex-shrinkflex-basis 这三个属性是控制 flexbox 布局中弹性伸缩的重要属性,非常方便实用。熟练掌握它们的使用可以让我们更好地控制弹性布局,实现更加灵活的网页布局。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值