弹性盒
flex
布局是现在最常用的一种布局方式,而均匀分布、按比例分布等等也是我们最常见的一种需求。而 flex
这个属性恰恰能满足我们的日常需求。
属性讲解
flex-grow
flex-grow
属性定义了项目的放大比例,默认为 0
,即如果存在剩余空间,也不放大。如果所有项目的 flex-grow
属性都为 1
,则它们将等分剩余空间。
也就是说,如果我们的需求是要均匀分布几个盒子,那就可以不设宽度,然后设置 flex-grow
为 1
,这样它们就会均匀地填充剩余空间。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div class="main mt30">
<div class="item" style="background: khaki;"></div>
<div class="item" style="background: pink;"></div>
<div class="item" style="background: skyblue;"></div>
</div>
</template>
<style lang="scss" scoped>
.main {
display: flex;
height: 200px;
.item {
flex-grow: 1; //平均分配剩余空间
height: 100%;
}
}
</style>
这是最常用的,简化写法为 flex: 1;
。但有个弊端,只考虑 flex-grow
的情况下,不适用于换行。
flex-shrink
flex-shrink
属性定义了项目的缩小比例,默认为 1
,即如果空间不足,该项目将缩小。如果所有项目的 flex-shrink
属性都为 1
,当空间不足时,都将等比例缩小。
目前这个属性我用的是比较少的,一般不改变,使用默认值。
flex-basis
flex-basis
属性定义了在分配多余空间之前,项目占据的主轴空间(宽度)。默认值为 auto
,即项目的本来大小。
简单来说就是这个最初的空间分配,分配了之后,flex-grow
再去分配剩余空间。下面的两个例子都是在 flex-basis
为 auto
的情况下处理的。
初始有空间
当某个盒子初始有空间时,使用 flex-grow
并不能使所有的盒子的宽度是 「一致」的,因为是分配剩余空间。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div class="main mt30">
<div class="item" style="background: skyblue;">
你好哦,今天是元气满满的一天!
</div>
<div class="item" style="background: pink;"></div>
<div class="item" style="background: khaki;"></div>
</div>
</template>
<style lang="scss" scoped>
.main {
display: flex;
height: 200px;
.item {
flex-grow: 1;
height: 100%;
}
}
</style>
第一个 div
有了内容,也就是说初始是有空间的,因此 flex-grow
并不能使所有的盒子的宽度是 「一致」的。但是分配的空间是均匀的。
如上图,盒子的宽度并不相等,但是分配的空间是均匀的。
初始没有空间
没有初始空间,就是默认的情况,盒子里无内容,就和 flex-grow: 1;
一样的效果。
设置初始空间
设置 flex-basis
可以指定初始空间,然后 flex-grow
再去分配剩余空间,就可以做到均匀分配了,以上的「均匀分配」的例子中,盒子都是没有内容的,所以可认为初始空间是 0
。因此,设置 flex-basis: 0;
后,分配的空间就是均匀的了。
1
2
3
4
5
6
7
8
9
10
11
<style lang="scss" scoped>
.main {
display: flex;
height: 200px;
.item {
flex-grow: 1;
flex-basis: 0; //设置初始空间为0
height: 100%;
}
}
</style>
例子
现在有一个需求,多个盒子均匀分布,每行 4 个盒子,超过了则换行,每个盒子的宽度一致。
这里用到了上面的三个属性,但有一个误区,认为 flex-grow
和「」挂钩了,那就错了。如果 flex-grow
为 1
,在同行中确实均匀分布了,但如果该行是最后一行,只有两个盒子,那将「均分」剩余空间,就会造成一个盒子占据了 2
个位置。
因此,重心应该放在 flex-basis
上,分配初始空间,然后不分配剩余空间。这种操作类似于设置百分比。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<template>
<div class="main mt30">
<div class="item" style="background: skyblue"></div>
<div class="item" style="background: pink"></div>
<div class="item" style="background: khaki"></div>
<div class="item" style="background: khaki"></div>
<div class="item" style="background: khaki"></div>
<div class="item" style="background: khaki"></div>
<div class="item" style="background: khaki"></div>
<div class="item" style="background: khaki"></div>
<div class="item" style="background: khaki"></div>
</div>
</template>
<style lang="scss" scoped>
.main {
$gap: 15px;
display: flex;
flex-wrap: wrap;
gap: $gap;
.item {
height: 100px;
border-radius: 10px;
flex: 0 0 calc((100% - 3 * $gap) / 4); //分配初始空间,不分配剩余空间
}
}
</style>
这里 flex: 0 0 calc((100% - 3 * $gap) / 4)
是简写,意思是 flex-grow: 0
、flex-shrink: 0
、flex-basis: calc((100% - 3 * $gap) / 4)
。
flex-grow: 0
是不分配剩余空间,目的是针对做后一行不满 4 个的情况。