flex布局是非常强大的布局方式,它能轻易完成我们能想到的大部分布局,类似圣杯布局、双飞翼布局等等,它非常灵活,兼容性也很好,在项目中经常被使用到。大多数同学应该都是从阮一峰老师的 这篇博文 了解到flex的,虽是15年写的,但毫不过时,依然有很强的引导性。
但是阮老师对于flex-basis、flex-grow、flex-shrink这三个属性只是一笔带过,没有去深入讲它,我一直对这三个属性都是云里雾里的(脑壳笨🤣),在网上也未找到很好的讲解,最近写页面写的比较多,一直在用flex布局,有没搞懂的感觉很不舒服,故自己研究了一下,做下记录,若有错误欢迎指正
基础demo
HTML
<div class="box">
<span class="item">1</span>
<span class="item">2</span>
<span class="item">3</span>
</div>
CSS
.box {
width: 300px;
height: 100px;
border: 1px solid black;
display: flex;
}
.item {
font-size: 25px;
color: white;
display: inline-block;
text-align: center;
line-height: 100px;
}
flex-basis
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。 —— 阮老师博客定义
我们先给每个item一个不同的width
.item:nth-child(1) {
width: 50px;
background-color: red;
}
.item:nth-child(2) {
width: 100px;
background-color: rgb(0, 204, 255);
}
.item:nth-child(3) {
width: 100px;
background-color: rgb(0, 255, 64);
}
(容器flex布局,flex-direction默认为row,水平排列。align-items默认为stretch,item未设高度,填满整个容器。我们没有给item设置flex-basis属性,默认值为auto)
现在我们给第一个item给个flex-basis属性,值为100px
.item:nth-child(1) {
width: 50px;
background-color: red;
flex-basis: 100px;
}
我们发现第一个item的width被flex-basis替代了,所以我们可得出 结论
item的flex-basis未设置或为auto时,item的width有效
item的flex-basis有值时,width就被替代,无效了
flex-grow
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。 —— 阮老师博客定义
我们还是先给每个item一个不同的width(跟上面的第一个一样的,我只是搬下来了)
.item:nth-child(1) {
width: 50px;
background-color: red;
}
.item:nth-child(2) {
width: 100px;
background-color: rgb(0, 204, 255);
}
.item:nth-child(3) {
width: 100px;
background-color: rgb(0, 255, 64);
}
父容器div.box的width有300px,但是三个item加起来才250px,还有50px的剩余空间。若是此时你想这50px的剩余空间被这三个项目以你的安排来占满,那么flex-grow就排上用场了
flex-grow属性默认为0,就是不占剩余空间。我们若想第一个item把剩余空间全占了,那就
.item:nth-child(1) {
width: 50px;
background-color: red;
flex-grow: 1;
}
.item:nth-child(2) {
width: 100px;
background-color: rgb(0, 204, 255);
}
.item:nth-child(3) {
width: 100px;
background-color: rgb(0, 255, 64);
}
此时第一个item的flex-grow是1,另外两个都是0,自然就被第一个独吞了
若是我们想第一二三个item以一、二、三的比例来瓜分剩余空间
.item:nth-child(1) {
width: 50px;
background-color: red;
flex-grow: 1;
}
.item:nth-child(2) {
width: 100px;
background-color: rgb(0, 204, 255);
flex-grow: 2;
}
.item:nth-child(3) {
width: 100px;
background-color: rgb(0, 255, 64);
flex-grow: 3;
}
那么第一个item实际宽度就是:50 + ( 1 / 6) * 50 = 58.333333333
第二个:100 + (2 / 6) * 50 = 116.6666666666
第三个:100 + (3 / 6) * 50 = 125
flex-grow属性默认值为0,不会参与瓜分剩余空间
剩余空间会按item的flex-grow属性值来瓜分
flex-shrink
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。 —— 阮老师博客定义
按照惯例,还是给每个item不同的width,这次不同一点,宽度和要超过div.box的width
.item:nth-child(1) {
width: 100px;
background-color: red;
}
.item:nth-child(2) {
width: 150px;
background-color: rgb(0, 204, 255);
}
.item:nth-child(3) {
width: 200px;
background-color: rgb(0, 255, 64);
}
可发现,虽然三个item的宽度和超过了div.box的width,超出部分有150px,但是并没有超出div.box,而是每个item都被”挤回去了“,这是因为每个item的flex-shrink属性默认都是1,它会按宽度比例缩小
flex-shrink和flex-grow不同,它会综合考虑每个item的宽度比和flex-shrink比,最终依次相乘做最后的比较,再用这个比值作为被缩减的宽度比
flex-grow之所以只看flex-grow的比值,不考虑宽度之比,是因为它只是去占有剩余空间,而跟每个item自身的width无关
我们可通过 计算 验证:
它们的宽度比为:2:3:4
flex-shink比为:1:1:1
则被缩减的宽度比为:2:3:4
所以第一个item的实际宽度:100 - (150 / 9) * 2 = 66.66666666
第二个:150 - (150 / 9) * 3 = 100
第三个:200 - (150 / 9) * 4 = 133.3333333333
我们可以再验证一个复杂点的:
.item:nth-child(1) {
width: 100px;
background-color: red;
flex-shrink: 3;
}
.item:nth-child(2) {
width: 150px;
flex-shrink: 4;
background-color: rgb(0, 204, 255);
}
.item:nth-child(3) {
width: 200px;
flex-shrink: 2;
background-color: rgb(0, 255, 64);
}
宽度比:2:3:4
flex-shrink比:3:4:2
被缩减的宽度比:3:6:4
所以第一个:100 - (150 / 13) * 3 = 65.384615384615384615
第二个:150 - (150 / 13) * 6 = 80.7692307692307692307
第三个:200 - (150 / 13) * 4 = 153.84615384615384615
经验证是正确的
还有个问题,如果每个item的flex-shrink的值都为0会怎样呢?
聪明的你应该想到了,会超出父元素div.
总结
- flex-basis
item的flex-basis未设置或为auto时,item的width有效
item的flex-basis有值时,width就被替代,无效了 - flex-grow
flex-grow属性默认值为0,不会参与瓜分剩余空间
剩余空间会按所以item的flex-grow属性值的比值来瓜分
flex-grow之所以只看flex-grow的比值,不考虑宽度之比,是因为它只是去占有剩余空间,跟每个item自身的width无关 - flex-shrink
flex-shrink属性默认为1,它会按宽度比例缩小,为0时,不会缩小
flex-shrink和flex-grow不同,它会综合考虑每个item的宽度比和flex-shrink比,最终依次相乘做最后的比较,再用这个比值作为被缩减的宽度比
当父容器内部的item宽度和超过父容器宽度时且item的flex-shrink都为0时会超出父容器
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。