【曾以为CSS牛逼了,然而并没有系列】
暂且不谈flex和box什么关系。单一个flex的用法,宝宝就懵逼了。
flex这个东西跟background一样,被称为shorthand属性,复合属性,我的理解是可以作为一系列属性的缩写。
先从简单的来看,给父元素设置flex环境:
.parent {
display: flex;
/* width: 600px; */
background-color: #eee;
margin-top: 100px;
}
孩儿们设置固定宽高:
.child:nth-child(1) {
background-color: salmon;
}
.child:nth-child(2) {
background-color: skyblue;
}
.child:nth-child(3) {
background-color: bisque;
}
.child {
width: 100px;
height: 100px;
}
效果是:乖乖依次排列,各自宽度为100px。
这时给child1单独设置一个
flex:1
.child:nth-child(1) {
background-color: salmon;
flex: 1;
}
好哒,不管父元素多宽,除去child2、child3两个的宽度,都被child1占满了,也就是说child1已经完全抛弃了自己原来的宽度。
然后child1不动,再给child2单独设置一个
flex:2
,为了看清楚运算,父元素宽固定设置为600px。
.parent {
display: flex;
width: 600px;
background-color: #eee;
margin-top: 100px;
}
.child:nth-child(1){
background-color: salmon;
flex: 1;
}
.child:nth-child(2) {
background-color: skyblue;
flex: 2;
}
好哒,child3依然保持着100px,但child2、child1已经按照2:1的比例,平分了(parent-child3)的宽度
然后呢,child3也不干了,凭什么挤我一个,我也要设置一个
flex:2
好哒,这个时候三个child都抛弃了自己原本的宽度,完全按照1:2:2的比例平分了parent的宽度,就算parent不固定宽度,也是一样的结果:
以上就是单独一个flex的使用效果。
flex-grow什么鬼?默认是0我知道。
officially,指定扩展比率,即剩余空间是正值时此「flex子项」相对于「flex容器」里其他「flex子项」能分配到空间比例。
flex-grow: <number> 拒绝负值!拒绝黄赌毒
这就要讲一下“剩余空间”这个东西,顾名思义,就是parent减去孩儿们的宽度,剩下的空间。孩儿们设置了flex-grow这个东西,是要商量一下各自分配他们爹的剩余空间是多少的。
.child:nth-child(1){
background-color: salmon;
flex-grow: 1;
}
.child:nth-child(2){
background-color: skyblue;
flex-grow: 2;
}
.child:nth-child(3){
background-color: bisque;
flex-grow: 2;
}
好哒,这个时候父元素600-100*3,还剩300的剩余量,那么孩子们就会按照1:2:2的比例剐分这300的剩余,也就是:
child1:100+(300*1/(1+2+2))=160,
child2 == child3:100+(300*2/(1+2+2))=220
however!
这个时候我手一欠改了一下flex属性,变成了这样:
.child:nth-child(1){
background-color: salmon;
flex-grow: 1;
}
.child:nth-child(2){
background-color: skyblue;
flex: 2;
}
.child:nth-child(3){
background-color: bisque;
flex: 2;
}
为了效果明显,把parent的宽度改到了900px。
然后就发生了我无法理解的事情!!谁能告诉我这260和320到底是怎么出来的?!。。
于是和无敌的众宝研究了一下,最终还是众宝查手册得出了结果,终于知道flex计算的时候到底经历什么(心也是够累了):
好的,这个问题我们最后来说。带着疑问先把flex-shrink和flex-basis讲完。
flex-shrink什么鬼?默认是1我知道。
officially,"指定收缩比率,即剩余空间是负值时此「flex子项」相对于「flex容器」里其他「flex子项」能收缩的空间比例"。
flex-shrink: <number> 拒绝负值!拒绝黄赌毒
so,我的理解就是shrink只有在需要“缩”的时候才用得上,那就是子元素的宽度加起来超过了父元素的宽度。好了,伸的时候有福同享,缩的时候有难要同当了。这时候大家要“共享”空间才行,“共享”的原则就是按照各自的shrink来看到底谁该“缩”多少,shrink大就多“缩”,shrink小就少"缩",正所谓责任越大承担就越重。
flex-basis什么鬼?默认是auto我知道。
officially, “设置或检测弹性盒伸缩基准值”、“指定伸缩基准值,即在根据伸缩比率计算出剩余空间的分布之前,「flex子项」长度的起始数值”
flex-basis: <length>拒绝负值!拒绝黄赌毒 / <percentage>拒绝负值!拒绝黄赌毒 / auto / content(基于内容自动计算宽度)
也就说,作为孩子,我本身是有一个“基准”宽度的。在flex-basis:auto
的情况下,取的是width
的值;在flex-basis:0
的情况下,width有值也是没啥用的。
其实不管什么时候,basis和grow、shrink是要配合着一起来用的,只不过没有明显设置的时候,都取了他们的默认值。
flex为一个值的时候,默认都表示什么(flex: grow shrink basis)
- flex : 1 [ flex: 1 1 0%]
- flex : auto [ flex: 1 1 auto]
- flex: none [ flex: 0 0 auto]
- flex: 0 auto [ flex: initial] [ flex: 0 1 auto]
了解了basis、grow、shrink到底是干什么用的之后,总结一下下:
在flex环境下,计算的步骤
- basis1 + basis2 + basis3 (假设其和是basisAll)
- 比较父元素宽度(parentWidth)和basisAll的大小
- parentWidth > basisAll,说明有剩余空间,需要“伸”
怎么“伸”呢:
把(parentWidth-basisAll)按照各自grow的比例(g1、g2、g3)分配给孩儿们,孩儿们拿着分到的growWidth加上原来的basis,就是各自最终的宽度。
childWidth1 = basis1 + (parentWidth-basisAll)*(g1/(g1+g2+g3))
childWidth2 = basis2 + (parentWidth-basisAll)*(g2/(g1+g2+g3))
childWidth3 = basis3 + (parentWidth-basisAll)*(g3/(g1+g2+g3)) - parentWidth < basisAll,说明爹的空间不够用,需要“缩”
怎么“缩”呢:
计算basis1*shrink1 + basis2*shrink2 + basis3*shrink3(假设和为basisShrinkAll),总的溢出量basisAll-parentWidth
把basisAll-parentWidth按照各自shrink的比例(s1、s2、s3)分配给孩儿们(和grow的计算有所不同)然后孩儿们用自己的basis减去分给自己的这个量。
childWidth1 = basis1 - (basis1*shrink1/basisShrinkAll * (basisAll-parentWidth))
childWidth2 = basis2 - (basis2*shrink2/basisShrinkAll * (basisAll-parentWidth))
childWidth3 = basis3 - (basis3*shrink3/basisShrinkAll * (basisAll-parentWidth))
好了,现在回头去看刚才宝宝懵逼的那个情况:
.child:nth-child(1){
background-color: salmon;
flex-grow: 1;
//相当于是flex在initial( 0 1 auto)的情况下,加了一个flex-grow,变成了flex: 1 1 auto,basis是auto,取其width的值100px
}
.child:nth-child(2){
background-color: skyblue;
flex: 2; //flex: 2 2 0%
}
.child:nth-child(3){
background-color: bisque;
flex: 2; //flex: 2 2 0%
}
//parent宽度为900px, 孩子们各自的宽度为100px(相当于flex-basis)
我们一步步来算下:
- 三个basis相加100px+0+0 < parentWidth(900px),因此要“伸”
- 剩余空间为900px-100px == 800px
- 把这800px按照1:2:2的比例分配给child1、child2、child3(160px、320px、320px)
- 最终结果:
child1 == 100px + 160px == 260px、
child2 == 0 + 320px == 320px、
child3 == 0 + 320px == 320px。