碎碎念
有了flex布局,我们可以轻松实现以往float,position甚至更为复杂的布局。本文不讲基本的flex用法,如果你对flex还不够了解,阮一峰Flex 布局教程:语法篇 - 阮一峰的网络日志的这篇文章是你接触flex的首选。
采用 Flex 布局的元素,称为 Flex 容器(flex container),简称"容器"。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称"项目"。
首先,flex布局发生在父元素和子元素之间,父容器需要声明display: flex;使之变为一个flex容器,子元素随即根据自身的属性来规划父容器内的空间。
grow与剩余空间
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大。
什么是剩余空间呢?一个flex容器中包含一条水平从左向右的主轴和一条垂直从上到下的交叉轴。剩余空间就是父容器在主轴的方向上还有多少没被项目占据的空间。
举个例子
<div class="container">
<span class="B1"></span>
<span class="B2"></span>
<span class="B3"></span>
</div>
Container是flex容器,B1,B2,B3时项目,假设前者width为500px,后者各为100px,那么剩余空间 = 500px - 300px。就是这么清晰明了。
那么flex-grow就很好理解了,分配了该属性的项目就是在索取剩余空间,默认是0,也就是都不索取剩余空间。假如我们对B1设置flex-grow: 1;,那么B1就独吞了剩下的200px,变成300px的一个大项目。同理,此时B2再设置flex:2;,那么说明B2也参与到瓜分剩余空间中来,并且他是占据了剩余空间中的2份,那么此时父容器就会把剩余空间分为3份,然后1份给到B1,2份给到B2,如下面这样子:
basis
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小,一般取值是px。
说实话,看了一边也不大理解怎么个意思。
其实这个属性值的作用也就是width的替代品。 如果项目设置了flex-basis或者width,那么在规划空间之前,他们会先跟父容器预约这么多的空间,然后剩下的才是归入到剩余空间,然后父容器再把剩余空间分配给设置了flex-grow的容器。
注意,如果同时设置flex-basis和width,那么width属性会被覆盖,也就是说flex-basis的优先级比width高。有一点需要注意,如果flex-basis和width其中有一个是auto,那么另外一个非auto的属性优先级会更高。
另外,flex-basis和width为auto值,那最后的空间就是根据内容多少来定的,内容多占据的水平空间就多。
shrink
好了,上面讲了这么多,你们应该都明白了把。 有人会想,不就这样嘛,很容易啊,核心不就是对剩余空间的分配吗?
是的,**核心就是对剩余空间的分配方式。**但是,父容器中项目的排列是否还有其它情况?可以发现,上面讲的例子B1 B2 B3的宽度总和都是没有超过父容器的宽度的。 那如果三个子容器的宽度和超过父容器的宽度呢?那还有剩余空间可以分配吗,此时浏览器又是怎么处理呢?
注意,flex环境默认是不换行的,即使父容器宽度不够也不会,除非设置flex-wrap来换行。
此时我们会发现,B1设置的flex-grow没有作用,不但没有获取到剩余空间,他的空间甚至是比他定义的300px还要小,而且我们发现B2和B3的空间也相应的被压缩了。 那么这里的问题就是:1、为什么flex-grow没有作用,反而被压缩呢?2、三个容器的压缩比例是这样的呢?
这就是这一节的重点了flex-shrink
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。
为什么flex-grow没有作用?
同样的,三个容器处于flex环境中,所以布局之前,父容器还是会计算剩余空间。 这一次计算的结果是这样的:剩余空间=500px - 300px - 160px - 120px = -80px,剩余空间是一个负数所以很容易理解第一个问题,即使是设置了flex-grow,但是由于没有剩余空间,所以B1分配到的空间是0。
三个容器的压缩比例是怎样的呢?
由于flex环境的父容器的宽度500px是不会变,所以为了是子容器的宽度和最多为父容器的宽度,那就只有两个办法:第一个是使子容器换行,第二个是压缩子容器使之刚好撑满父容器的宽度。 因为flex子容器是默认不换行的,所以这里不做讨论。而第二种压缩,实际上就是上面例子表现出来的样式。现在就遇到了上面第二个问题,这三个的压缩比例是多少呢,各自需要压缩的空间是多少呢?
这个时候就需要谈谈flex-shrink,这个属性其实就是定义一个子容器的压缩比例。他的默认值是1,所以上面那个例子,就是三个子容器压缩的比例是一样的 1:1:1。 如果此时我们设置B1的压缩比例是2,那会怎样呢?
我们可以发现,B1被压缩的更多了。而B2和B3得到了跟多的空间。那我们怎么得出他们各自的压缩率呢?我们假设B2 B3的压缩率是X1,那么B1的压缩率就是X2了,那就有了如下方程:
X2 = 2 * X1;
500 = 300 * X2 + 160 * X1 + 120 * X1;
总结
1、剩余空间=父容器空间-子容器1的flex-basis/width - 子容器2的lex-basis/width - … 2、如果父容器空间不够,就走压缩flex-shrink,否则走扩张flex-grow; 3、如果你希望某个容器在任何时候都不被压缩,那设置flex-shrink:0; 4、如果子容器的的flex-basis设置为0(width也可以,不过flex-basis更符合语义),那么计算剩余空间的时候将不会为子容器预留空间。 5、如果子容器的的flex-basis设置为auto(width也可以,不过flex-basis更符合语义),那么计算剩余空间的时候将会根据子容器内容的多少来预留空间。