最近在项目开发的时候遇到一个问题,就是在 flex 布局的时候,设置了 flex 元素高度的时候,发现高度设置完没有生效,需要设置 flex 元素的 flex-shrink 属性为 0 才能生效,这是为啥?
想要理解这个问题,需要理解下面这三个 flex 元素的属性
flex-grow
:该元素获得(伸张)多少正可用空间(positive free space)?flex-shrink
:该元素要消除(收缩)多少负可用空间(negative free space)?flex-basis
:在该元素未伸张和收缩之前,它的大小是多少?
这篇文章主要介绍通过这三个属性的使用来探索 flex 的布局机制。
这里先介绍一下 fle 布局中可用空间的概念,CSS中的"可用空间"(available space)是指在布局中可供使用的剩余空间,它通常指的是容器内的剩余可分配空间。
举个例子说明一下可用空间,假设在 1 个 500px 的容器中,我们有 3 个 100px 宽的元素,那么这 3 个元素需要占 300px 的宽,剩下 200px 就是可用空间。在默认情况下,flexbox 的行为会把这 200px 的空间留在最后一个元素的后面。
通过几个例子来探讨这三个属性的使用
# flex 容器高度足够高的布局场景
标题的含义具体是指,flex 容器的高度比所有 flex 元素高度的总和还要高,即能完全容纳下 flex 元素。这种情况下通常留出一部分可用空间。
在下面这种布局情况下,假设我们希望最后一个蓝色元素填满剩余的可用空间应该如何设置?
<div class="flexlayout-container-one">
<div class="item-one">第一个</div>
<div class="item-two item-size">第二个</div>
<div class="item-three item-size"></div>
</div>
<style>
.flexlayout-container-one {
display: flex;
flex-direction: row;
width: 400px;
height: 100px;
background-color: aquamarine;
}
.item-one { background-color: red; }
.item-two {
background-color: green;
width: 100px;
height: 100px;
}
.item-three {
background-color: blue;
width: 150px;
height: 100px;
}
</style>
# flex-basis 简介
先别急,我们先理解一下 flex-basis
的概念,flex-basis
指定了 flex 元素在主轴方向上的初始大小。flex-basis
可以被设置为一个固定的长度值(如像素、百分比等)或者 auto
,当 flex-basis
被设置为 auto
时,弹性元素的初始尺寸会根据内容的大小自动确定。
注意:flex 元素的
width
属性和flex-basis
属性是有区别的,只不过当 width 属性设置为 150px 的时候 flex-basis 也是 150px
结合上面这个例子,item-one
元素的 flex-basis
值为 auto,item-two
和 item-three
的 width
元素设置 150px,即 flex-basis
也是 150px.
# flex-grow 简介
flex-grow
是 Flexbox 布局中的一个属性,用于定义弹性元素在主轴(通常是水平轴)上的放大比例,以便在剩余的可用空间中分配额外的空间。
flex-grow
接受一个非负数值作为参数,表示元素的放大比例。这个值越大,元素在可用空间中获得的额外空间就越多。默认情况下,元素的 flex-grow
值为 0,意味着它不会在分配额外空间时放大。
OK,现在的知识储备已经足够解决上面的问题了。
回到我们例子中,我们想让最后的蓝色节点填满可用空间,可以如下设置这样蓝色节点
.item-three {
background-color: blue;
width: 150px;
height: 100px;
flex-grow: 1; /* 元素会在剩余空间中均等地分配额外空间 */
}
设置了 flex-grow
为 1 的元素会均等的共享剩余的可用空间,目前只有蓝色节点设置了 flex-grow
为 1,所以蓝色区域共享了所有的剩余空间。值得说明一下的是,这时候蓝色节点的宽度虽然设置的是 150px,但是宽度的设置已经不起作用了。
如果想要蓝绿色共享可用空间,则将绿色的节点元素也设置 flex-grow
为 1。
.item-two {
background-color: green;
width: 100px;
height: 100px;
flex-grow: 1; /* 元素会在剩余空间中均等地分配额外空间 */
}
效果如图,蓝色和绿色节点平分了剩余的控件,假设可用空间为 100px,则 50px 分给绿色节点,50px 分给蓝色节点。最终绿色节点为 150px, 蓝色节点为 200px。
# flex 容器高度不足的布局场景
标题的含义具体是指,flex 容器的高度比所有 flex 元素高度的总和要小,即能不能完全容纳下 flex 元素。
在下面这种布局情况下,我们希望红色和绿色能够按照正常的显示,然后蓝色节点被压缩也没关系。
<div class="flexlayout-container-two">
<div class="item-one">第一个</div>
<div class="item-two item-size">第二个</div>
<div class="item-three item-size"></div>
</div>
.flexlayout-container-two {
margin-top: 20px;
display: flex;
flex-direction: row;
width: 200px;
height: 100px;
.item-one { background-color: red; }
.item-two {
background-color: green;
width: 100px;
height: 100px;
}
.item-three {
background-color: blue;
width: 150px;
height: 100px;
}
}
回到我们上面的知识点,目前这种布局下是没有可用空间的,空间都被填满了,而且本来设置好宽度的元素,宽度也被挤压了。这种情况怎么达到预期的效果?
# flex-shrink 简介
flex-shrink
是 Flexbox 布局中的一个属性,用于定义弹性元素在主轴上的缩小比例。当容器的空间不足以容纳所有弹性元素时,具有非零 flex-shrink
值的元素会按照其缩小比例来收缩,以适应剩余的空间。
flex-shrink
属性接受一个非负数值作为参数,表示元素的缩小比例。默认情况下,元素的 flex-shrink
值为 1,意味着它会根据容器空间的不足等比例地缩小。如果一个元素的 flex-shrink
值为 0,它将不会在容器空间不足时缩小。
我自己理解
flex-shrink
和flex-grow
是两组相对的概念,一个是出现在空间不足的场景,一个是出现在空间富裕的场景。
了解了 flex-shrink
属性之后,我们回到上面的例子,因为默认 flex-shrink
是 1,上面所有 flex 容器内的元素都会等比例缩小,想要不缩小的话就要设置 flex-shrink
为 0,所以我们对红色和绿色元素节点进行如下配置,得到效果如图
.item-one {
background-color: red;
flex-shrink: 0;
}
.item-two {
background-color: green;
width: 100px;
height: 100px;
flex-shrink: 0;
}
# 回到起始问题
写到这儿也就足够能解释文章开通的问题了「在 flex 布局的时候,设置了 flex 元素高度的时候,发现高度设置完没有生效,需要设置 flex 元素的 flex-shrink 属性为 0 才能生效,这是为啥?」
因为 flex 容器高度不够,设置 height 没有生效,设置 flex-shrink
为 0 的话,就不会因为空间不足而压缩了。这个方式
因为 flex 容器高度不够,设置 height 没有生效,设置 flex-shrink
为 0 的话,就不会因为空间不足而压缩了。
这种设置方式其实很适合在列表高度不固定的时候,进行列布局,想要在列表底部撑起一块空白区域的场景,单独设置一个空白节点,然后设置起 flex-shrink
为 0,然后设置想要撑起的空白区域的高度即可。
# 总结
我自己理解 flex-grow
是用在可用空间富裕的场景下,flex-shrink
用在没有可用空间或者 flex 容器没有设置 height 的情况下。
参考地址: