说到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=" 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; 是等比分配吗?请看运行结果 } }
运行结果: 觉得奇怪吗?明明对每个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%; } }
再次测试一下:
ok, 很完美的解决了。我们上面的那种写法是将flex-grow flex-shrink flex-basis 分开写的情况。根据上面单值写法的解析,其实我们直接写成 flex: 1; 就不会出现上述问题。因为 flex: 1; 等价于 flex: 1 1 0;
flex-shink 属性在使用时也有和flex-grow 属性相同的需要注意的点。
下面谈这个案例中另一个需要解决的问题, 当一个完整的单词很长的话,如果只忽略子元素的原始大小还不太好用。依旧达不到等比分配的效果。如下
这时需要多加一个属性设置 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元素上设置 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%; } }