[css3] 深入理解 css3 中的 flex-grow、flex-shrink、flex-basic

深入理解 css3 中的 flex-grow、flex-shrink、flex-basic

原文链接: 深入理解css3中的flex-grow、flex-shrink、flex-basis

flex为 css 的布局带来了新的时代,作为一个重构工程师,我们再也不用局限于 float 和 position,特别是在移动端,我们可以利用 flex 轻松实现以往 float 和 position 很难实现甚至是无法实现的布局。本文主要讲解 flex 的三个子属性:flex-grow、flex-shrink、flex-basis。他们只是博大精深的 flex 中的一部分,本文默认你对 flex 已经有初步的了解,如果不了解,建议选看看这里:

flex 布局发生在父容器和子容器之间。父容器需要有 flex 的环境display: flex;,子容器才能根据自身的属性来布局,简单的说,就是瓜分父容器的空间。相反就是说如果父容器没有 flex 的环境,那么子容器就无法使用 flex 的规则来划分父容器的空间。

讲到瓜分父容器的空间,那么首先需要讲一个很重要的词:剩余空间
什么是剩余空间呢?具备 flex 环境的父窗口,通常是有一条主轴和一条侧轴,默认情况下主轴就是水平从左向右的,侧轴是垂直从上到下的(类似书写模式)。剩余空间是父容器在主轴的方向上还有多少可用的空间。比如看下面这段 html 结构:

<div class="container">
  <span class="B1"></span>
  <span class="B2"></span>
  <span class="B3"></span>
</div>

container 就是父容器,B1 B2 B3 就是子容器,假如 container 的 width 是 100px,那么剩余空间就是: 500px - B1.width - B2.width - B3.width。嗯就是这么简单!

flex-grow

flex-grow (default: 0)知道了剩余空间的概念,首先来看一下 flex-grow。上面那个例子,我们假设 container 的 width 是 500px,现在我们再假设 B1、B2、B3的 width 是 100px,那么剩余空间就是 500 - 100 * 3 = 200。知道了剩余空间有什么用呢?这个时候 flex-grow 就该出场了,假如我们这个时候对 B1设置 flex-grow: 1,那么我们会发现,B1把 B2 和 B3 都挤到右边了,也就是说剩余的 200px 空间都被 B1 占据了,所以此时 B1 的 width 比实际设置的值要大。

<style type="text/css">
.wrap {
  border: 1px solid red;
  height: 500px;
  display: flex;
  width: 500px;
}

.wrap .B {
  width: 100px;
  height: 100px;
  box-sizing: border-box;
}

.B1 {
  background-color:rgba(255,255,0,.5);
  flex-grow: 1;
}

.B2{
    background-color:rgba(255,0,255,.5);
}
.B3{
    background-color:rgba(0,255,255,.5);
}

</style>
<div class="wrap">
  <div class="B B1">B1</div>
  <div class="B B2">B2</div>
  <div class="B B3">B3</div>
</div>

在这里插入图片描述
在 jsrun 中打开示例

所以这里 flex-grow 的意思已经很明显了,就是索取父容器的剩余空间,默认值是 0,就是三个子容器都不索取剩余空间。但是当 B1 设置为 1的时候,剩余空间就会被分成一份,然后都给了 B1。如果此时 B2设置了 flex-grow: 2,那么说明 B2 也参与到瓜分剩余空间中来,并且他是占据了剩余空间中的 2 份,那么此时父容器就会把剩余空间分成 3 份,然后 1 份给到 B1,2份给到 B2,如下面这样子。
B1的宽度为:100 + 200 / 3 * 1
B2 的宽度为:100 + 200 / 3 * 2
B3的宽度为:100

<style type="text/css">
.wrap {
  border: 1px solid red;
  height: 500px;
  display: flex;
  width: 500px;
}

.wrap .B {
  width: 100px;
  height: 100px;
  box-sizing: border-box;
}

.B1 {
  background-color:rgba(255,255,0,.5);
  flex-grow: 1;
}

.B2{
    background-color:rgba(255,0,255,.5);
  flex-grow: 2;
}
.B3{
    background-color:rgba(0,255,255,.5);
}

</style>
<div class="wrap">
  <div class="B B1">B1</div>
  <div class="B B2">B2</div>
  <div class="B B3">B3</div>
</div>

flex-basis

flex-basis (default:auto) 初次见 flex-basis 这个属性,还挺疑惑的,不知道它是用来干嘛的。后来研究发现,这个属性值的作用也就是 width 的替代品。如果子容器设置了 flex-basis 或者 width,那么在分配空间之间,他们会先跟父容器预约这么多的空间,然后剩下的才是归入的剩余空间,然后父容器再把剩余空间分配给设置了 flex-grow 的容器。如果同时设置 flex-basis 和 width,那么 width 属性会被覆盖,也就是说 flex-basis 的优先级比 width 高。有一点需要注意,如果 flex-basis 和 width 其中有一个是 auto,那么另外一个非auto 的属性优先级会更高。

<div class="wrap">
  <div class="B B1">B1</div>
  <div class="B B2">B2</div>
  <div class="B B3">B3</div>
</div>
.wrap {
  border: 1px solid red;
  height: 500px;
  display: flex;
  width: 500px;
}

.wrap .B {
  width: 100px;
  height: 100px;
  box-sizing: border-box;
}

.B1 {
  background-color:rgba(255,255,0,.5);
  flex-grow: 1;
}

.B2{
    background-color:rgba(255,0,255,.5);
    flex-basis: 150px;
}
.B3{
    background-color:rgba(0,255,255,.5);
}

在这里插入图片描述
在 jsrun 中打开示例

tips: flex-basis 和 width 为 auto 值,那最后的空间就是根据内容多少来定的,内容多占据的水平空间就多。

<div class="wrap">
  <div class="B B1">B1</div>
  <div class="B B2">B2</div>
  <div class="B B3">B3</div>
</div>
.wrap {
  border: 1px solid red;
  height: 500px;
  display: flex;
  width: 500px;
}

.wrap .B {
  height: 100px;
}

.B1 {
  background-color:rgba(255,255,0,.5);
  width: 100px;
  flex-grow: 1;
}

.B2{
    background-color:rgba(255,0,255,.5);
  flex-basis: auto;

}
.B3{
    background-color:rgba(0,255,255,.5);
  width: auto;
}

在这里插入图片描述
在 jsrun 中打开示例

flex-shrink

flex-shrink(default: 1)好了, 上面讲了这么多,你们应该都明白了把。有人会想,不就这样嘛,很容易啊,不就是剩余空间的分配吗?

是的,上面讲的都是剩余空间的分配。但是,你有没有想过还有没有其他的情况呢?可以发现, 上面讲的例子 B1 B2 B3 的宽度总和都是没有超过父容器的宽度的。那如果三个子容器的宽度和超过父容器的宽度呢?那还有剩余空间可以分配吗?此时浏览器又是怎么处理呢?请看下面:

tips: flex 环境默认是不换行的,即使父容器宽度不够也不会,除非设置 flex-wrap 来换行

<div class="wrap">
  <div class="B B1">B1</div>
  <div class="B B2">B2</div>
  <div class="B B3">B3</div>
</div>
.wrap {
  border: 1px solid red;
  height: 500px;
  display: flex;
  width: 500px;
}

.wrap .B {
  height: 100px;
  box-sizing: border-box;
}

.B1 {
  background-color:rgba(255,255,0,.5);
  flex-grow: 1;
  width: 300px;
}

.B2{
    background-color:rgba(255,0,255,.5);
  width: 160px;
}
.B3{
    background-color:rgba(0,255,255,.5);
  width: 120px;
}

在这里插入图片描述
在 jsrun 中打开示例

此时我们会发现,B1 设置的 flex-grow 没有作用,不但没有获取到剩余空间,他的空间甚至是比他定义的 300px 还要小,而且我们发现 B2 和 B3 的空间也相应的被压缩了。那么这里的问题是:

  • 为什么 flex-grow 没有作用,反而被压缩呢?
  • 三个容器的压缩比例是怎样的呢?

这就是这一节的重点了flex-shrink

同样的,三个容器处于 flex 环境中,所以布局之前,父容器还是会计算剩余空间。这一次计算的结果是这样的:剩余空间 = 500px - 300px - 160px - 120px = -80px,剩余空间是一个负数所以很容易理解第一个问题,即使是设置了 flex-grow,但
是由于没有剩余空间,所以 B1 分配到的空间是0。

由于 flex 环境的父容器的宽度是 500px 是不会变,所以为了是子容器的宽度和最多为父容器的宽度,那就只有两个办法:

  • 第一个是使子容器换行
  • 第二个是压缩子容器使之刚好撑满父容器的宽度。

因为 flex 子容器是默认不换行的,所以这里不做讨论。而第二种压缩,实际上就是上面例子表现出来的样式。现在就遇到了上面第二个问题,这三个的压缩比例是多少呢,各自需要压缩的空间是多少呢?

这个时候就需要谈谈 flex-shrink,这个属性其实就是定义了一个子容器的压缩比例。他的默认值是 1,所以上面那个例子,就是三个子容器压缩的比例是一样的: 1: 1: 1。如果此时我们设置 B1 的压缩比例是 2 那会怎样呢?

<div class="wrap">
  <div class="B B1">B1</div>
  <div class="B B2">B2</div>
  <div class="B B3">B3</div>
</div>
.wrap {
  border: 1px solid red;
  height: 500px;
  display: flex;
  width: 500px;
}

.wrap .B {
  height: 100px;
  box-sizing: border-box;
}

.B1 {
  background-color:rgba(255,255,0,.5);
  flex-shrink: 2;
  width: 300px;
}

.B2{
    background-color:rgba(255,0,255,.5);
  width: 160px;
}
.B3{
    background-color:rgba(0,255,255,.5);
  width: 120px;
}

在这里插入图片描述
在 jsrun 中打开示例

设「压缩率」为 x,则 300(1 - 2x) + 160(1 - x) + 120(1 - x) = 500
x = 1 / 11
B1的宽度为 300 (1 - 2 /11 ) = 245.45

总结

通过上面的分析, 我们可以得出这样几个结论:

  • 剩余空间 = 父容器空间-子容器1.flex-basis/width - 子容器2.flex-basis/width - …
  • 如果父容器空间不够,就走压缩 flex-shrink,否则走扩张 flex-grow;
  • 如果你希望某个容器在任何时候都不被压缩,那设置 flex-shrink: 0;
  • 如果子容器的 flex-basis 设置为 0(width 也可以,不过 flex-basis 更符合语义),那么计算剩余空间的时候将不会为子容器预留空间。
  • 如果子容器的 flex-basis 设置为 auto(width 也可以,不过 flex-basis 更符合语义),那么计算剩余空间的时候将会根据子容器内容的多少来预留空间。
  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
CSS3flexbox布局是一种非常强大的布局方式,可以通过一些属性来实现弹性伸缩和对齐。其flex-growflex-shrinkflex-basis就是控制弹性伸缩的重要属性。 flex-grow 属性 flex-grow 属性用于指定元素在弹性容器的伸展比率,即当元素所在容器有剩余空间时,元素按照比例分配剩余空间。默认值为 0,即当剩余空间不足时,元素不会伸展。 例如,当一个容器有两个元素,一个 flex-grow 值为 1,另一个为 2,则第二个元素在容器有剩余空间时会比第一个元素多分配一倍的剩余空间。 flex-shrink 属性 flex-shrink 属性用于指定元素在弹性容器的收缩比率,即当元素所在容器空间不足时,元素按照比例收缩。默认值为 1,即元素会自动收缩。 例如,当一个容器有两个元素,一个 flex-shrink 值为 1,另一个为 2,则第二个元素在容器空间不足时会比第一个元素多收缩一倍。 非常重要的一点是,如果所有元素的 flex-shrink 属性值都为 0,则它们不会收缩。 flex-basis 属性 flex-basis 属性用于指定元素在弹性容器的基准值,即元素在不伸展或收缩的情况下所占据的空间。默认值为 auto,即元素的大小由其本身的大小决定。 例如,当一个容器有两个元素,一个 flex-basis 值为 100px,另一个为 200px,则第一个元素在不伸展或收缩的情况下会占据 100px 的空间。 综合运用 这三个属性通常一起使用,例如: flex: 1 0 auto; 这个属性的意思是元素在弹性容器会按照 flex-grow 属性的比例伸展,但不会收缩,基准值由 flex-basis 决定。 总结 flex-growflex-shrinkflex-basis 这三个属性是控制 flexbox 布局弹性伸缩的重要属性,非常方便实用。熟练掌握它们的使用可以让我们更好地控制弹性布局,实现更加灵活的网页布局。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值