Flexbox 支持对元素大小的灵活控制。本文重点说说 flex-basis
、flex-shrink
、flex-grow
的算法。
flex-basis
指定了 flex
元素在主轴方向上的初始大小。默认值是 auto
,关于 auto 这个属性值 MDN 上还有一段简史,可以了解下。直接上:chestnut:
<div class="container">
<div class="item one">200px</div>
<div class="item two">500px</div>
</div>
.container {
display: flex;
width: 1000px;
height: 50px;
background-color: green;
}
.item {
flex-basis: auto;
height: 100%;
text-align: center;
line-height: 50px;
}
.one {
width: 200px;
background-color: red;
}
.two {
width: 500px;
background-color: orange;
}
关键字 auto
的意思好像是把 width
或 height
设置为自动,实际上并不是这么一回事。auto
的意思是这个项目可以从对应的属性(width
或 height
)那里获得主尺寸,如果没有设置主尺寸,根据内容确定大小——类似于行内块或者浮动元素!
flex-basis
还能设置成 content
值,意思是根据项目内容确定大小——跟 auto
的区别在于忽略 width
和 heigh
t 设置的主尺寸。浏览器对 content
关键字支持度不一致!!
flex: 0 会是什么效果呢?
可以看到,子元素的 width
都失效了。其实它是子元素的最小宽度(隐形最小宽度——即便你通过属性指定可伸缩项要收缩,但它们可能也不会收缩到可容纳内容的大小之下。)。将 500px
替换成一个 DOM:
<div class="item two">
<div class="two-child">400px</div>
</div>
.two-child {
width: 400px;
}
结果如下图所示:
flex-grow
属性表示剩余空间的一个比值,默认值是0。回到最初 200px
、 500px
的例子,200 + 500 = 700
并没有完全撑满整个父元素 .container
的宽度,剩余的宽度是如何处理的呢?
.one {
flex-grow: 1;
}
.two {
flex-grow: 1;
}
通过上述样式,就可以将剩余的 300px
平均分给.one .two
元素。
如果结合下面样式会是怎样的呢?
.item {
flex-basis: 0%;
}
答案是 .one .two
平分1000px
,即各 500px
。不受子元素的影响。
flex-shrink
父元素宽度不够时就要压缩子元素的宽度,通过 flex-shrink 配置。缩小不比扩大那么简单,缩小的计算方法会复杂一些。复杂的根源在于,再大的子元素也不能导致小元素压缩得不见了。还是用最前面的例子:
.one {
width: 600px;
flex-shrink: 1;
}
.two {
width: 800px;
flex-shrink: 1;
}
按照自动放大的方式,应该是 (600+800-1000)/2
, .one
应该是 400px
,.two
应该是600px
:
结果 .one
是 428.58px
,这是如何计算过来的呢?
.one = (600 * 1/(600*1 + 800*1))*1000 ≈ 428.58
.two = (800 * 1/(600*1 + 800*1))*1000 ≈ 571.42
我们换一个比例来验证一下想法:
.one {
width: 600px;
flex-shrink: 2;
}
.two {
width: 800px;
flex-shrink: 3;
}
通过计算我们得到:
.one = (600*2/(600*2 + 800*3))*400 ≈ 133.33
.two = (800*3/(600*2 + 800*3))*400 ≈ 266.67
所以 .one
的宽度是 600 - 133.33 px, .two
的宽度是 800 - 266.67 px。下面验证一下结果:
Bingo!正如我们的猜想那样。这里用 A 表示第一个子元素,B 表示第二个子元素。计算公式如下:
A 压缩的大小 = (A.flex-shrink * A.flex-basis) / (A.flex-shrink * A.flex-basis + B.flex-shrink * B.flex-basis) * 总体超出的宽度
B 压缩的大小 = (B.flex-shrink * B.flex-basis) / (A.flex-shrink * A.flex-basis + B.flex-shrink * B.flex-basis) * 总体超出的宽度
flex
flex
是 flex-grow
、flex-shrink
、flex-basis
的缩写,当 flex-basis
是 0 的时候一定/必须/务必要带上单位,0px 或 0% 任君选择。
留一道思考题,上述最后一个例子,如果给 .one 一个 min-width: 500px;
计算会有什么不同吗?
欢迎指点缺陷,更多好文前往博客!