flex-grow和flex-dhrink都是CSS3的新增的弹性盒子的属性。弹性盒子这种布局方式使得开发人员能够将网页在pc端和移动端的不同大小屏幕下能够以不同的布局正常显示。相对于浮动布局更加方便,不用为清除浮动想很多解决方法。并且元素大小也能随着屏幕大小缩放,用户在实际体验上感觉会很好。
来到正题,flex-grow和flex-shrink。前者是当容器下元素的(以下都以宽度为例,但不仅限于宽度)没有完全填充的时候,使用flex-grow填充剩余的部分,后者则是宽度超出容器宽度,把超出的部分压缩进容器内。
首先看看不设置flex-grow的效果
// HTML部分
// CSS部分
.box{
width: 600px;
height: 200px;
border: 1px solid;
display: flex;
}
.box div:nth-of-type(1){
width: 100px;
height: 100px;
background-color: red;
}
.box div:nth-of-type(2){
width: 150px;
height: 100px;
background-color: skyblue;
}
.box div:nth-of-type(3){
width: 200px;
height: 100px;
background-color: yellow;
}
效果
三个子元素排列在一行并且多余出150px的宽度。那么这时候加上flex-grow,只需要改动三个子元素
.box div:nth-of-type(1){
width: 100px;
height: 100px;
background-color: red;
flex-grow: 1;
}
.box div:nth-of-type(2){
width: 150px;
height: 100px;
background-color: skyblue;
flex-grow: 1;
}
.box div:nth-of-type(3){
width: 200px;
height: 100px;
background-color: yellow;
flex-grow: 1;
}
此时给值都给1,看看效果
在元素原本基础宽度上每个元素都加了50px的宽度正好填充满父容器。再来看看flex-grow值不一样的时候
.box div:nth-of-type(1){
width: 100px;
height: 100px;
background-color: red;
flex-grow: 1;
}
.box div:nth-of-type(2){
width: 150px;
height: 100px;
background-color: skyblue;
flex-grow: 2;
}
.box div:nth-of-type(3){
width: 200px;
height: 100px;
background-color: yellow;
flex-grow: 3;
}
效果图
我分别给三个元素依次设置了flex-grow等于1 2 3。从效果图上来看每个元素宽度依次增加了25px 50px 275px。结合这两个案例可以很轻松的得到计算公式。每一个元素增加的量等于多余的部分除以所有元素总的flex-grow值然后再乘以当前元素的flex-grow值。
但是还是需要说明的就是,我们都知道组成一个元素可见区域不只是有内容,还有内边距边框,这里需要注意的就是加上内容和边框的话就需要把边框内边距加上之后算剩余宽度再去分配内容。如果加上了内边距边框但是不想改变原有的布局分配(纯粹通过元素宽度来进行分配)那么可以加上box-sizing: border-box;可以解决此问题。
容器的一行不仅仅只会有一个元素,多个元素下将会如何压缩,首先看个小例子
// HTML部分
<div class="content">
<div class="left">div>
<div class="center">div>
<div class="right">div>
div>
// CSS部分
.content{
display: flex;
width: 400px;
height: 200px;
border: 1px solid;
}
.left, .center, .right{
height: 200px;
}
.left{
width: 100px;
background-color: aqua;
}
.center{
width: 200px;
background-color: bisque;
}
.right{
width: 300px;
background-color: cadetblue;
}
可以看到在这个例子下并没有flex-grow这个属性,但是父元素还是设置了display:fex;的。那么看看没有这个属性下会是什么样的情况。
从效果图上来看,本应超出父容器的元素并没有超出去,这时候可以想应该是被压缩了。我们查阅一下CSS3的文档找出属性flex-shrink,可以看到他的默认值是1。那么此时,我们可以尝试想一下,就算没有去设置flex-shrink,是不是在flex下也会按照flex-shrink==1计算。通过代码可以看出三个元素之和比父容器多了200px。按照每个元素相等压缩。每个元素将压缩约66.67px,那么最终的效果就应该是第一个元素宽33.33px,第二个元素宽133.33px,第三个元素宽将是233.33px。得到此结果结合效果图来看,并不是这样。与我们计算的有偏差,那么就不是按照这样的方法来压缩。
换一种思路,他们不是均分的压缩,那么就是不均分的压缩,那么不均分的压缩是根据什么来压缩。不均分肯定三个元素有不一样的地方,那通过代码看三个元素不一样的地方是宽度和颜色,颜色肯定不参与压缩计算的,那只剩下宽度,三个元素的宽度依次是100px 200px 300px。把他们宽度按比例计算 ,他们三个的比是2:3:4。按照这个比例来试着计算一下压缩值,多余了200px ,计算出三个元素依次压缩后的值约为66.67px 133.33px 200px。可以看到就是上图元素的宽度。这样就可以得出即使没有设置flex-shrink容器内元素也能按每个元素宽度的比例压缩。
看完了没有设置的再来看看设置了flex-shrink的,直接看代码。同样只会改动三个子元素。
.left{
width: 100px;
background-color: aqua;
flex-shrink: 1;
}
.center{
width: 200px;
background-color: bisque;
flex-shrink: 1;
}
.right{
width: 300px;
background-color: cadetblue;
flex-shrink: 3;
}
看效果
这就是结果,你会发现如果按照之前flex-shrink的计算方式来计算这个,不能对上。因为这时三个元素的flex-shrink值不一样了。如果你没接触这个,恐怕想破脑袋也不会知道这个是怎么计算的。直接看上计算公式。
flex-shrink计算方法
value = box1.width * box1.flex-shrink + box2.width * box2.flex-shrink + box3.width * box3.flex-shrink
box1.width = box1.width - box1.width * box1.flex-shrink / value * 总宽度溢出去的宽度
box2.width = box2.width - box2.width * box2.flex-shrink / value * 总宽度溢出去的宽度
box3.width = box3.width - box1.width * box3.flex-shrink / value * 总宽度溢出去的宽度
根据计算公式,可以轻易的算出每个元素宽度依次是83.33px 166.67px 150px。和上图也都能对应上。读到这里,肯定以为这就是最终的计算公式了。其实回头看一下flex-shrink最后我说了个加上内边距和边框的情况。这个肯定也是要加上内边距边框来看看结果的。
只改变第一个元素,给他左右边框个加一个内边距
.left{
width: 100px;
background-color: aqua;
flex-shrink: 1;
padding: 0 10px;
}
效果图
和没加是不一样的。加上padding唯一改变的就是超出的部分的宽度,所以唯一改变的就是超出的宽度加上20再去计算。根据计算公式,得出来结果81.67px 163.33px 135px。第一个元素加上内边距就为101.67px,对比数据一致。