关于flex布局的几个难点总结

1.前言

好久没有写css了,当我回顾flex布局时候,发现有些知识已经遗忘了,所以专程写一篇文章来记录下,这篇文章不会介绍flex的基础用法,只是记录下flex布局中其中比较难理解,比较容易忘记的部分!

2. flex属性各种写法

flex 的缩写: flex-grow、flex-shrink、flex-basis, 它有很多种缩略的写法,平时我们用的比较少(因为很多人不知道),下面来详细了解下,具体各自什么意思后面是详细讲解!

1. 如果用了弹性布局,没写flex属性,flex 的默认值是 0 1 auto

flex:0 1 auto;

2.当 flex 取值为一个数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%,

flex:1; /*等价于*/ flex:1 1 0%;

3. 当 flex 取值为一个长度或百分比,该值为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1

flex:20px; /*等价于*/ flex:1 1 20px;
flex:20%; /*等价于*/ flex:1 1 20px;

4.当 flex 取值为两个数字,则两值视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%

flex:1 1; /*等价于*/ flex:1 1 0%;

5.当 flex 取值为 auto,则值为 1 1 auto

flex:auto; /*等价于*/ flex:1 1 auto;

6. 当 flex 取值为 none,则值为 0 0 auto

flex:none; /*等价于*/ flex:0 0 auto;

7. 当 flex 取值为一个数字和一个长度或百分比,则为 flex-grow 和 flex-basis 的值,flex-shrink 取 1,

flex:1 20px; /*等价于*/ flex:1 1 20px;
flex:1 20%; /*等价于*/ flex:1 1 20%;

结论:

  1. 当flex为none或者默认不写情况下flex-grow为0,其他情况下都有值(默认值1或者其他数字)
  2. 当flex为none时候flex-shrink为0,其他情况下都有值(默认值1或者其他数字)
  3. 当flex为一个数字或者两个数字时候flex-basic为0,其他情况下都有值(默认值auto或其他数字或百分比)
2. 1 flex-basis

这个属性的意思是元素的初始长度

<style>
    .container {
        display: flex;
        width: 600px;
        border: 1px solid #ccc;
    }
    .a1 {
        height: 200px;
        flex: 0 0 30%;
        width: 100px;
        background-color: cyan;
    }

    .a2 {
        height: 200px;
        background-color: darkgreen;
        width: 200px;
    }

    .a3 {
        height: 200px;
        background-color: red;
        width: 300px;
    }
</style>
<body>
    <div class="container">
        <div class="a1"></div>
        <div class="a2"></div>
        <div class="a3"></div>
    </div>
</body>

在这里插入图片描述
上面设置了flex: 0 0 30%; 意思我flex-grow为0, flex-shrink为0,flex-basis为600*30%=180px!

<style>
    .container {
        display: flex;
        width: 600px;
        border: 1px solid #ccc;
    }
    .a1 {
        height: 200px;
        flex: 0 0 auto;
        background-color: cyan;
    }

    .a2 {
        height: 200px;
        background-color: darkgreen;
        width: 200px;
    }

    .a3 {
        height: 200px;
        background-color: red;
        width: 300px;
    }
</style>
<body>
    <div class="container">
        <div class="a1">1234</div>
        <div class="a2"></div>
        <div class="a3"></div>
    </div>
</body>

在这里插入图片描述
上面设置了flex: 0 0 auto;并且我没设置width属性, 所以a1的长度就为内容的长度!

<style>
    .container {
        display: flex;
        width: 600px;
        border: 1px solid #ccc;
    }
    .a1 {
        height: 200px;
        flex: 0 0 auto;
        width: 100px;
        background-color: cyan;
    }

    .a2 {
        height: 200px;
        background-color: darkgreen;
        width: 200px;
    }

    .a3 {
        height: 200px;
        background-color: red;
        width: 300px;
    }
</style>
<body>
    <div class="container">
        <div class="a1">1234</div>
        <div class="a2"></div>
        <div class="a3"></div>
    </div>
</body>

在这里插入图片描述
上面设置了flex: 0 0 auto;并且我设置width属性100px, 所以a1的长度就为wdith长度100px!

结论:

  1. 当flex-basis有值的时候(auto除外),他的优先级大于width属性的。
  2. 当它为百分比时候是相对父容器的。
  3. 当它为auto时候,如果有width就是width长度,如果没有width就是元素内容的长度。
2. 2 flex-grow

flex-grow 属性用于设置或检索弹性盒子的扩展比率。如果元素不是弹性盒对象的元素,则 flex-grow 属性不起作用。

<style>
    .container {
        display: flex;
        width: 800px;
        border: 1px solid #ccc;
    }
    .a1 {
        height: 200px;
        flex:1 auto;
        width: 100px;
        background-color: cyan;
    }

    .a2 {
        flex:1 auto;
        height: 200px;
        background-color: darkgreen;
        width: 200px;
    }

    .a3 {
        flex:1 auto;
        height: 200px;
        background-color: red;
        width: 300px;
    }
</style>
<body>
    <div class="container">
        <div class="a1"></div>
        <div class="a2"></div>
        <div class="a3"></div>
    </div>
</body>

在这里插入图片描述
这里每个子元素都设置了 flex:1 auto; 所有的子元素的总长度 a1(100px)+a2(200px)+a3(300px)=600px,父元素的长度为800,多出了200px,因为每个子元素都设置了flex-grow为1,相当于每个元素都有1/3的扩展比例,那么a1长度就变成100px+1/3*200=166.6px,a2长度就变成200px+1/3*200=266.6px,a3长度就变成300px+1/3*200=266.6px,

有些同学会问 你为什么不设置flex:1?
根据上面的缩写flex:1相当于flex:1 1 0%,由于flex-basis的优先级高于width,所以子元素的宽度都为0px,所有子元素总宽度为0px,父的长度为800,因为每个子元素flex-grow为1,所以每个子元素的长度为1/3*800=266.6px,所以这也是为什么flex为数值可以各自按比例分配给各个子元素

2. 3 flex-shrink

flex-shrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。如果元素不是弹性盒对象的元素,则 flex-shrink 属性不起作用。

<style>
    .container {
        display: flex;
        width: 400px;
        border: 1px solid #ccc;
    }
    .a1 {
        height: 200px;
        flex:0 2 auto;
        width: 100px;
        background-color: cyan;
    }

    .a2 {
        flex:0 1 auto;
        height: 200px;
        background-color: darkgreen;
        width: 200px;
    }

    .a3 {
        flex:0 1 auto;
        height: 200px;
        background-color: red;
        width: 300px;
    }

</style>
<body>
    <div class="container">
        <div class="a1"></div>
        <div class="a2"></div>
        <div class="a3"></div>
    </div>
</body>

从上面代码来看所有子的总宽度为a1(100px)+a2(200px)+a3(300px)=600px,父元素的宽度为400px,不够?少了200px,同理按照上面的扩展规律,a1收缩比例为2/4,a1,a3收缩比例为1/4,所以a1的宽度为100-2/4200=0px,a2的宽度为200-1/4200=150px,a3的宽度为300-1/4*200=250px,但结果是这样吗?看下图
在这里插入图片描述
看图显示的结果和上面算的不对,其实收缩规则和扩展规律算法不一样,按扩展的那种算法如果a1的flex-shrink再大些,那么a1的宽度都要变成负数了?所以flex-shrink并非严格比例的缩小,它还会考虑元素本身的大小,来看下正确的计算方式,a1的缩小系数为2*100/2*100+1*200+3*100=2/7,a2的缩小系数为1*200/2*100+1*200+3*100=2/7,a3的缩小系数为1*300/2*100+1*200+3*100=3/7,所以a1的宽度为100-2/7*200=42.86px,a1的宽度为200-2/7*200=142.86px,a3的宽度为300-3/7*200=214.29px,算出的结果和上面一致


3. align-items和align-content的区别

先看初始代码

<style>
    .container {
        display: flex;
        width: 800px;
        border: 1px solid #aaa;
    }

    .a1 {
        height: 60px;
        width: 200px;
        background-color: cyan;
    }

    .a2 {
        height: 100px;
        background-color: darkgreen;
        width: 200px;
    }

    .a3 {
        height: 200px;
        background-color: red;
        width: 200px;
    }

    .a4 {
        height: 80px;
        background-color: darkkhaki;
        width: 200px;
    }

    .a5 {
        height: 100px;
        background-color: darkseagreen;
        width: 200px;
    }

    .a6 {
        height: 90px;
        background-color: deeppink;
        width: 200px;
    }
</style>

<body>
    <div class="container">
        <div class="a1"></div>
        <div class="a2"></div>
        <div class="a3"></div>
        <div class="a4"></div>
        <div class="a5"></div>
        <div class="a6"></div>
    </div>
</body>

先来设置 align-items: center

    .container {
        display: flex;
        width: 800px;
        align-items: center;
        border: 1px solid #aaa;
        flex-wrap: nowrap;
    }

当父容器没设置高度且布局nowrap只有一行的情况下align-items是有效果的,居中对齐!
在这里插入图片描述

    .container {
        display: flex;
        width: 800px;
        align-content: center;
        border: 1px solid #aaa;
    }

当父容器没设置高度且布局nowrap只有一行的情况下 align-content: center无效!还是贴顶对齐!
在这里插入图片描述

    .container {
        display: flex;
        width: 800px;
        height: 500px;
        align-items: center;
        border: 1px solid #aaa;
    }

当父容器设置了高度且布局nowrap只有一行的情况下align-items是有效果的,居中对齐!

在这里插入图片描述

    .container {
        display: flex;
        width: 800px;
        height: 500px;
        align-content: center;
        border: 1px solid #aaa;
    }

当父容器设置了高度且布局nowrap只有一行的情况下 align-content: center无效!还是贴顶对齐!

在这里插入图片描述

    .container {
        display: flex;
        width: 800px;
        flex-wrap: wrap;
        align-items: center;
        border: 1px solid #aaa;
    }

当父容器没设置高度且布局wrap多行的情况下align-items是有效果的,居中对齐!
在这里插入图片描述

    .container {
        display: flex;
        width: 800px;
        flex-wrap: wrap;
        align-content: center;
        border: 1px solid #aaa;
    }

当父容器没设置高度且布局wrap多行情况下 align-content: center无效!还是贴顶对齐!
在这里插入图片描述

   .container {
        display: flex;
        width: 800px;
        flex-wrap: wrap;
        align-items: center;
        border: 1px solid #aaa;
    }

当父容器设置高度且布局wrap多行的情况下align-items是有效果的,但是行与行之间有空隙,因为flex布局会将交叉轴上的多余空间按行数平均分给每行,然后每行各自按自己所在的行居中对齐
在这里插入图片描述

    .container {
        display: flex;
        width: 800px;
        height: 500px;
        flex-wrap: wrap;
        align-content: center;
        border: 1px solid #aaa;
    }

当父容器没设置高度且布局wrap多行情况下 align-content: center有效!整体居中对齐,与justify-content对齐相似!

在这里插入图片描述

还有一种另类情况(这种情况用的很少)

<style>
    .container {
        display: flex;
        width: 800px;
        height: 500px;
        flex-wrap: wrap;
        align-content: center;
        border: 1px solid #aaa;
    }

    .a1 {
        height: 60px;
        width: 200px;
        background-color: cyan;
    }

    .a2 {
        height: 100px;
        background-color: darkgreen;
        width: 200px;
    }

    .a3 {
        height: 200px;
        background-color: red;
        width: 200px;
    }

</style>

<body>
    <div class="container">
        <div class="a1"></div>
        <div class="a2"></div>
        <div class="a3"></div>
    </div>
</body>

当父设置了高,子元素只有一行的时候,并且设置 flex-wrap: wrap的情况下 align-content会生效!
在这里插入图片描述

结论:

  1. align-items不管父有没有高,单行还是多行,都会生效,注意它的基本单位是每一个子项(每个元素),以元素为单位的,它会将交叉轴上的多余空间按行数平均分给每行,所以每行的高度是平均分给每行的高度+每行子元素最高的高度,然后每个元素在这个高度范围内进行flex-start flex-end center等进行布局!
  2. align-content的基本单位是每行,每行的高度是一行中最高元素的高度,一定是在 flex-wrap: wrap(不管单行还是多行) 且 父有固定高度时候才会生效!,它的对齐方式和主轴justify-content对齐方式相似!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值