解析flex属性:flex:1究竟是什么

420 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第18天,点击查看活动详情

解析flex属性:flex:1究竟是什么

实现页面中的footer保持在页面底部功能,有一个非常简单的方法:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html, body{
            height: 100%;
        }
        #container{
            display: flex;
            flex-direction: column;
            min-height: 100%;
        }
        #header{
            height: 100px;
            background-color: aquamarine;
        }
        #content{
            flex: 1;
            background-color: burlywood;
        }
        #footer{
            height: 120px;
            background-color: brown;
        }
        .box{
            height: 300px;
        }
    </style>
</head>
<body>
    <div id="container">
        <div id="header"></div>
        <div id="content">
            <div class="box"></div>
        </div>
        <div id="footer"></div>
    </div>
</body>
</html>

将父容器的display设置为flex,flex-direaction设置为column,min-height设置为100%;再将需要伸缩的content部分设置flex:1。这样,可以实现footer一直固定在页面底部,当content内容足够多的时候,footer才会移动出屏幕。

flex:1到底是什么

flex实际上是flex-grow、flex-shrink和flex-basis三个属性的缩写。

flex:1 ==> flex:1 1 auto

flex-grow flex-grow属性指定了flex容器中剩余空间的多少应该被分配给项目。flex-grow设置的值为扩张因子,默认为0,剩余空间将会按照这个权重分别分配给子元素项目。

例如:父元素的宽度为500px,其中有两个元素A和B,A的宽度为100px,B的宽度为150px。假如不设置flex-grow属性,那么父元素的剩余宽度为500-(100+150)=250px。

<style>
#container {
    display: flex;
    width: 500px;
    margin: 20px;
    border: 1px solid#000;
}

#A {
    width: 100px;
    height: 200px;
    background-color: aqua;
}

#B {
    width: 150px;
    height: 200px;
    background-color: chocolate;
}
</style>

<div id="container">
    <div id="A">100px</div> 
    <div id="B">150px</div>
</div>

flex.png 假如A、B元素分别设置flex-grow的权重为a、b,那么A、B元素分别得到的剩余空间为250 * a/(a+b)、250 * b/(a+b)。

例:设置A的flex-grow为2,B的flex-grow为3,那么A元素的总宽度为100+250 * 2/(2+3)=200px,B元素的总宽度为150+250 * 3/(2+3)=300px。

#container {
    display: flex;
    width: 500px;
    margin: 20px;
    border: 1px solid#000;
}

#A {
    width: 100px;
    height: 200px;
    background-color: aqua;
    flex-grow: 2;
}

#B {
    width: 150px;
    height: 200px;
    background-color: chocolate;
    flex-grow: 3;
}

flex1.png

flex2.png

假如只有一个元素设置了flex-grow属性,那么该元素会得到所有剩余空间。

#container {
    display: flex;
    width: 500px;
    margin: 20px;
    border: 1px solid#000;
}

#A {
    width: 100px;
    height: 200px;
    background-color: aqua;
    flex-grow: 2;
}

#B {
    width: 150px;
    height: 200px;
    background-color: chocolate;
}

flex3.png

假如所有元素的flex-grow属性值加起来小于1,那么权重计算的分母将会按照1来计算。

例如:设置A的flex-grow为0.2,B的flex-grow为0.3,那么A的总宽度为100+(250 * 0.2)/1=150px,B的总宽度为100+(250 * 0.3)/1=225px。父元素剩余宽度为250 * (1-0.2-0.3)=125px。即父元素的剩余空间不会全部分配给子元素。

#container {
    display: flex;
    width: 500px;
    margin: 20px;
    border: 1px solid#000;
}

#A {
    width: 100px;
    height: 200px;
    background-color: aqua;
    flex-grow: 0.2;
}

#B {
    width: 150px;
    height: 200px;
    background-color: chocolate;
    flex-grow: 0.3;
}

flex4.png

flex5.png

<style>
#container {
    display: flex;
    width: 500px;
    margin: 20px;
    border: 1px solid#000;
}

#A {
    width: 250px;
    height: 200px;
    background-color: aqua;
}

#B {
    width: 350px;
    height: 200px;
    background-color: chocolate;
}

</style>

<div id="container">
    <div id="A">250px</div>
    <div id="B">350px</div>
</div>

flex6.png

flex7.png

假如都设置flex-shrink为0,那么元素将不会缩小,宽度会超出父元素的宽度。

flex8.png

和flex-grow一样,当各元素的flex-shrink之和不足1时,将不会收缩所有空间,而只收缩剩余空间中(flex-shrink总和/1)的比例的空间。

例:设A的flex-shrink为0.2,B的flex-shrink为0.3:

#container {
    display: flex;
    width: 500px;
    margin: 20px;
    border: 1px solid#000;
}
#A {
    width: 250px;
    height: 200px;
    background-color: aqua;
    flex-shrink: 0.2;
}

#B {
    width: 350px;
    height: 200px;
    background-color: chocolate;
    flex-shrink: 0.3;
}

此时,溢出的宽度为100px,但是能收缩的宽度只有100 * (0.2+0.3)=50px。A的缩小宽度为50 * (250*0.2/(250 * 0.2+350 * 0.3)≈16.12px,B的缩小宽度为50 * (350 * 0.3/(250 * 0.2+350 * 0.3)≈33.87px。

flex9.png

flex10.png

flex-basis flex-basis属性指定了flex元素在主轴方向上的初始大小。如果不使用box-sizing改变盒模型的话,那么这个属性就决定了flex元素的内容的尺寸。如果设置了flex-basis值,那么元素占用的空间为flex-basis值;如果没有设置或者设置为auto,那么元素占据的空间为元素的width/height值。

例:A元素设置了width为250px,同时设置了flex-basis为300px,那么A元素占据的空间为300px。B元素没有设置flex-basis,占据的空间为350px。

<style>
#container {
    display: flex;
    width: 700px;
    margin: 20px;
    border: 1px solid#000;
}
#A {
    width: 250px;
    height: 200px;
    background-color: aqua;
    flex-basis: 300px;
}

#B {
    width: 350px;
    height: 200px;
    background-color: chocolate;
    flex-shrink: 0.3;
}

</style>

<div id="container">
    <div id="A">250px</div>
    <div id="B">350px</div>
</div>

flex11.png

回到我们一开始的问题,flex的默认值为flex:0 1 auto。flex:1相当于设置了flex:1 1 auto。flex-grow属性为1,该元素将会占据容器中所有的剩余空间,所以可以轻易地做到footer元素一直保持在底部的效果。

参考 developer.mozilla.org/zh-CN/docs/… zhuanlan.zhihu.com/p/136223806 blog.csdn.net/m0_37058714… www.cnblogs.com/LangZ-/p/12…