说到flex布局,大家可能并不陌生。对于基本概念,大家应该也有所了解。这里可以推荐我看过的认为比较通俗易懂的博客,它就是阮一峰老师的flex布局博客, 感谢阮一峰老师的无私分享。

那么,了解过基本概念后。对于Flex布局我们常见的几个误区和经常遇到的所谓的坑是什么呢?这里,兼容性问题我就不讲了,不是本次博客的主要内容。下面我主要想讲讲flex布局使用的几个误区和常遇到的问题。

1. Flex属性的写法

  首先我们知道 flex: <number> <number> <length/percentage/cale> 实际上是flex-grow, flex-shrink, flex-basis三个属性的缩写。 

flex: flex-grow flex-shrink flex-basis

  那么这三个属性的初始值是什么呢?

flex-grow: 0;
flex-shrink: 1;
flex-basis: auto; 根据内容大小分配

  根据上面的基础认知,下面我们介绍flex属性的几种常见写法及解析

内置值写法
flex: auto; 等价于 flex: 1 1 auto; 元素会根据自身的宽度与高度来确定尺寸,但是会自行伸长以吸收flex容器中额外的自由空间,也会缩短至自身最小尺寸以适应容器.
flex: initial; 等价于 flex: 0 1 auto; 元素会根据自身宽高设置尺寸。它会缩短自身以适应容器,但不会伸长并吸收flex容器中的额外自由空间来适应容器.
flex: none; 等价于 flex: 0 0 auto; 元素会根据自身宽高来设置尺寸。它是完全非弹性的:既不会缩短,也不会伸长来适应flex容器


单值法
One value, unitless number: flex-grow
flex: <positive-number>; 等价于 flex: <positive-number> 1 0;


单值法
One value, unit number: flex-basis
flex: <unit-number>; 等价于 flex: 0 1 <unit-number>;元素有一个自定义的主轴上的宽度/高度 (单值法)

双值法
第一个值必须是无符号的 flex-grow | flex-shrink
flex: <positive-number> <positive-number>; 等价于 flex: <positive-number> <positive-number> 0;

双值法
第一个值必须是无符号的 flex-grow | flex-basis
flex: <positive-number> <unit-number/percentage/calc()> 等价于 flex: <positive-number> 1 <unit-number/percentage/calc()>

三值法
flex: <positive-number> <positive-number> <unit-number/percentage/calc()>

2. flex-grow: 1 真的是等比分配吗????

  如下例子是我们所认为的平均分配吗?

    <div id="main" style="width: 1000px; height:200px;">
      <div style="background-color:coral;">First</div>
      <div style="background-color:lightblue;">Second  I am long long long long long long long long long long long</div>
      <div style="background-color:khaki;">Third</div>
      <div style="background-color:pink;">Forth</div>
      <div style="background-color:lightgrey;">Fifth</div>
    </div>
    #main {
        display: flex;
        div {
            flex-grow: 1;    是等比分配吗?请看运行结果
        }
    }

  运行结果:flex布局精髓和填坑-LMLPHP               觉得奇怪吗?明明对每个div设置的都是 flex-grow: 1; 那么,他们为什么不是等比分配,全部是200px宽呢??? 这里就需要我们回到上面定义的地方从新理解一下flex-grow的含义。请注意 flex-grow的含义,通俗的讲,是按用户定义的比例去分配父元素剩余的空闲空间(出去子元素本身所占的空间之后剩余的空间)。这个地方通常是我们的误区之一。认为只要设了等比例分配,那么flex布局就会按等比例去分配。no no no.

  那么,怎么解决这个问题呢?其实再重新回到上面黄色部分的定义仔细读几遍,我们就会发现,问题实际上出在每个子元素本身所占的空间是不一样的,这才导致最终分配的全占比是不一样的。子元素的宽度 = 子元素本身的宽度 + 剩余空间的配比。上面的案例,其实剩余空间的配比是相等的,只是子元素原始本身的宽度不等,导致最终宽度是非等比例的。好的,知道问题就好解决了。 我们让flex布局在分配空间时忽略子元素本身的占比就可以了,这里我们肯定会想到属性 flex-basis,它就是控制子元素本身占比的,那么我们设置它为 flex-basis: 0%;

    #main {
        display: flex;
        div {
            flex-grow: 1;
            flex-basis: 0%;
        }
    }

再次测试一下:

flex布局精髓和填坑-LMLPHP

ok, 很完美的解决了。我们上面的那种写法是将flex-grow flex-shrink flex-basis 分开写的情况。根据上面单值写法的解析,其实我们直接写成 flex: 1; 就不会出现上述问题。因为 flex: 1; 等价于 flex: 1 1 0;

flex-shink 属性在使用时也有和flex-grow 属性相同的需要注意的点。

下面谈这个案例中另一个需要解决的问题, 当一个完整的单词很长的话,如果只忽略子元素的原始大小还不太好用。依旧达不到等比分配的效果。如下flex布局精髓和填坑-LMLPHP

这时需要多加一个属性设置 word-break: break-all/break-word; 就解决了

3. flex 和 width的坑

项目中遇到一个问题。利用了flex布局的元素,当该元素内部的子元素内容超过flex分配的空间后,flex分配比例失效。

<div class="view-list-item" [class.hyphens-words]="showHyphens"><div>{{ impact.currentState }}</div></div>
<div class="view-list-item" [class.hyphens-words]="showHyphens"><div>{{ impact.futureStateName }}</div></div>
<div class="view-list-item" [class.hyphens-words]="showHyphens"><div>{{ impact.changeDelta }}</div></div>
                      &:nth-child(3), &:nth-child(4), &:nth-child(5) {
                            flex: 9;
                            padding-right: 0px;
                            > div {
                                max-height: rem(60px);
                                padding-right: rem(10px);
                                overflow-y: auto;
                                width: 100%;
                            }
                        }

flex布局精髓和填坑-LMLPHP

解决方法: 在父的flex元素上设置 width:0px; 使得分配的空间大于设置的width;然后最终选择分配的空间,从而规避这个问题

                      &:nth-child(3), &:nth-child(4), &:nth-child(5) {
                            flex: 9;
                            width: 0px;
                            padding-right: 0px;
                            > div {
                                max-height: rem(60px);
                                padding-right: rem(10px);
                                overflow-y: auto;
                                width: 100%;
                            }
                        }
12-02 21:26