前言
在现代CSS布局中,Flexbox(弹性盒子)因其强大的对齐和空间分配能力,成为前端开发的核心工具之一。在Flex中可以设置非常多的属性,本文针对flex属性仔细介绍,慢慢介绍关于的它的所有细节。
flex属性解析
flex 是 CSS Flexbox 布局中的一个复合属性,它是三个子属性的复合: flex-grow、flex-shrink 和 flex-basis 。其中:
- flex-grow:定义项目在容器有剩余空间时的扩张比例。
- flex-shrink:定义项目在容器空间不足时的收缩比例。
- flex-basis:设置项目的初始基准尺寸(类似
width,但优先级更高)。
它们的默认值分别是:0 1 auto(不扩张、可收缩、基准尺寸为内容大小)
比如我们在业务中常见的写法flex: 1 实际上是为这三个子属性指定以下值:
flex-grow: 1flex-shrink: 1flex-basis: auto
那么这些属性到底有什么意义呢?我们该如何设置呢?请看下文。
flex的核心特性:空间分配
接下来我为大家仔细介绍Flex布局的核心用法:空间分配。分为两种情况:剩余空间和不足空间。接下来我们通过结合两个案例的方式来进行讲解两种情况,
实战项目一:flex-grow的扩张计算
当 父容器大小 > 所有子元素的 flex-basis 总宽度 时,存在剩余空间,按 flex-grow 比例分配。
下面的代码主轴为横轴,flex-grow、flex-shrink 和 flex-basis 用户都自己指定了具体的值,请你思考一下,告诉我页面中的left和right的宽度具体是多少?
<style>
*{
margin: 0;
padding: 0;
}
.container{
width: 600px;
height: 300px;
display: flex;
}
.left {
flex: 1 2 300px;
width: 300px;
background-color: red;
}
.right {
flex: 2 1 200px;
width: 200px;
background-color: blue;
}
</style>
<body>
<div class="container">
<!-- FFC 弹性格式化上下文 -->
<div class="left"></div>
<div class="right"></div>
</div>
</body>
下面,我们通过页面检查查看结果:left宽度为333.33px,right宽度为267.77px
接下来我们仔细分析是如何得到这个结果的
父元素的width是600px,两个子元素都都设置了flex-basis属性,其中,left的为300px,right的为200px。我们发现 600px > 300px+200px ,说明容器大小 > 所有项目的 flex-basis 总宽度,触发flex-grow的扩张运算。
计算步骤1:
计算剩余空间
剩余空间 = 父容器宽度 - (子元素1的flex-basis + 子元素2的flex-basis + ...)
案例中剩余空间为
600px - 300px - 200px = 100px
计算步骤2:
按flew-grow比例分配空间
子元素得到的空间 = 剩余空间 * (子元素的flex-grow / 总flex-grow)
案例中子元素得到的空间
left: (100px * 1/3) ≈ 33.33px
right: (100px * 2/3) ≈ 67.77px
计算步骤3:
得到最终宽度
子元素最终宽度 = flex-basis + 子元素得到的空间
所以这里得到最终宽度分别为:
left : 300px + 33.33px ≈ 333.33px
right : 200px + 67.77px ≈ 267.77px
实战项目二:flex-shrink的收缩计算
当 容器大小 < 所有项目的 flex-basis 总宽度 时,空间不足,按 flex-shrink 加权压缩。
下面的代码主轴为横轴,flex-grow、flex-shrink 和 flex-basis 用户都自己指定了具体的值,请你思考一下,告诉我页面中的left和right的宽度具体是多少?
<style>
*{
margin: 0;
padding: 0;
}
.container{
display: flex;
width: 600px;
height: 300px;
}
.left{
flex: 1 2 500px;
background-color: red;
}
.right{
flex: 2 1 400px;
background-color: blue;
}
</style>
<body>
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>
</body>
下面,我们通过页面检查查看结果:left宽度为285.717px,right宽度为314.283px
接下来我们仔细分析是如何得到这个结果的
父元素的width是600px,两个子元素都都设置了flex-basis属性,left的为500px,right的为400px。我们发现 600px < 500px+400px ,说明容器大小 < 所有项目的 flex-basis 总宽度,所以按 flex-shrink 加权压缩。
计算步骤1:
计算不足空间
不足空间 = (子元素1的flex-basis + 子元素2的flex-basis + ...) - 容器宽度
案例中不足空间为
(400px + 500px) - 600px = 300px
计算步骤2:
计算总权重
总权重 = (子元素1的flex-basis * 子元素1的flex-shrink) + (子元素2的flex-basis * 子元素2的flex-shrink)....
案例中总权重为
(500px * 2) + (400px * 1) = 1400px
计算步骤3:计算收缩比例
子元素收缩比例 = (子元素的flex-basis * 子元素的flex-shrink) / 总权重
案例中子元素的收缩比例为
left: (500px * 2) / 1400px = 5/7
right:(400px * 1) / 1400px = 2/7
计算步骤四:计算最终宽度
子元素的最终宽度 = 子元素的flex-basis - (收缩比例) * 不足空间
案例中子元素的最终宽度为
left: 500px - 5/7 * 300px = 285.717px
right: 400px - 2/7 * 300px = 314.283px
注意事项
在上面两个案例中,我们需要注意:
-
flex-basis的优先级:- 在主轴方向上,
flex-basis会覆盖width(除非flex-basis: auto)。 - 设置
flex-basis: 0会让项目完全依赖flex-grow分配空间(忽略内容宽度)。
- 在主轴方向上,
-
flex-shrink的特殊性:- 收缩计算时,
flex-shrink会乘以flex-basis作为权重,因此大尺寸项目收缩更多。 - 若
flex-shrink: 0,项目拒绝收缩,可能导致溢出容器。
- 收缩计算时,
-
最小尺寸限制:
- 即使计算后宽度为负,项目也不会小于其
min-content(除非显式设置min-width)。
- 即使计算后宽度为负,项目也不会小于其
最后,给出两种方式的差异总结:
flex-grow vs. flex-shrink 的核心差异
| 特性 | flex-grow (扩张) | flex-shrink (收缩) |
|---|---|---|
| 触发条件 | 容器有剩余空间时 | 容器空间不足时 |
| 计算逻辑 | 按比例分配剩余空间 | 按 flex-shrink × flex-basis 加权压缩 |
| 默认值 | 0(不扩张) | 1(允许收缩) |
| 权重影响 | 仅依赖 flex-grow 值 | 受 flex-shrink 和 flex-basis 共同影响 |
| 极端情况 | 若所有项目 flex-grow: 0,剩余空间留白 | 若所有项目 flex-shrink: 0,可能导致容器溢出 |