前言
前段时间被头条hr从库里捞起来了(去年面到三面打入冷宫),于是就接受了面试邀请,心想进不了也可以查缺补漏自己的不足。
其中就问了一道关于flex的问题:
1 | 面试官:`flex: 1` 是哪些属性的缩写? |
接下来我就来对flex对应的三个属性做个详解。
首先明确一点是,flex 属性是 flex-grow, flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto。
flex-grow
传统的布局是子容器在父容器中从左到右进行布局,应用 flex 进行布局,那么父容器一定设置 display: flex
,子容器要“占有”并且“瓜分”父容器的空间,如何占有、瓜分的策略就是弹性布局的策略。这里就要解释到“剩余空间”的概念:
子容器在父容器的“主轴”上还有多少空间可以“瓜分”,这个可以被“瓜分”的空间就叫做剩余空间。
flex-grow
属性定义弹性盒子项(flex-item)的放大比例(定义子容器的瓜分剩余空间的比例),默认为0,即如果存在剩余空间,也不放大(不会去瓜分)。
flex-shrink
如果子容器宽度超过父容器宽度,即使是设置了 flex-grow,但是由于没有剩余空间,就分配不到剩余空间了。这时候有两个办法:换行和压缩。由于 flex 默认不换行,那么压缩的话,怎么压缩呢,压缩多少?此时就需要用到 flex-shrink
属性了。
flex-shrink
属性定义了弹性盒子项(flex-item)的缩小比例,默认为1,即如果空间不足,该子容器将缩小。
如果所有子项的 flex-shrink
属性都为1,当空间不足时,都将等比例缩小。如果一个子项的 flex-shrink
属性为0,其他子项都为1,则空间不足时,前者不缩小。
此时,剩余空间的概念就转化成了“溢出空间”。
注意:
- 负值对该属性无效。
- 如果子容器没有超出父容器,设置 flex-shrink 无效
flex-basis
flex-basis
属性定义了在分配多余空间之前,子项占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
它可以设为跟 width 或 height 属性一样的值(比如350px),则子项将占据固定空间。既然是跟宽度相关,那么 max-width,min-width,width 和 flex-basis 的大小优先级是怎么样的。
max-width/min-width > flex-basis > width
理解完了这三个属性接下来就看一些我们平时常写的一些简写表示的意义。
flex 简写
flex 的默认值是以上三个属性值的组合。假设以上三个属性同样取默认值,则 flex 的默认值是 0 1 auto。
flex 取三个值
1 | .item { flex: 2 1 200px; } |
flex 取值为 none
当 flex 取值为 none,则计算值为 0 0 auto。
1 | .item { flex: none; } |
flex 取值为 auto
当 flex 取值为 auto,则计算值为 1 1 auto。
1 | .item { flex: auto; } |
flex 取值为 一个非负数
当 flex 取值为一个非负数字,则该数字为 flex-grow 值,flex-shrink 取 1,flex-basis 取 0%。
1 | .item { flex: 1; } |
flex 取值为 长度或百分比
当 flex 取值为一个长度或百分比,则视为 flex-basis 值,flex-grow 取 1,flex-shrink 取 1。
1 | .item { flex: 0%; } |
flex 取值为 两个非负数字
当 flex 取值为两个非负数字,则分别视为 flex-grow 和 flex-shrink 的值,flex-basis 取 0%。
1 | .item { flex: 1 2; } |
flex 取值为 一个非负数字和一个长度或百分比
当 flex 取值为一个非负数字和一个长度或百分比,则分别视为 flex-grow 和 flex-basis 的值,flex-shrink 取 1。
1 | .item { flex: 2 20px; } |
最后我们来用一个例子来计算子项的宽度。
栗子🌰
1 | <div class="parent"> |
当 item-1 的 flex-basis 取 0% 的时候,是把该项目视为零尺寸的,故即便声明其尺寸为 140px,也并没有什么用,形同虚设
而 item-2 的 flex-basis 取 auto 的时候,根据规则基准值使用值是主尺寸值即 100px,故这 100px 不会纳入剩余空间
主轴上父容器总尺寸:600px
剩余空间:
600px - 100px(item2的flex-basis值) - 200px(item3的flex-basis值) = 300px
伸缩放大系数之和(flex-grow值):
2(item1) + 2(item2) + 1(item3) = 5
每一份比例所占宽度:300 / 5 = 60px;
剩余空间分配如下:
- item1 和 item2 各分配 2/5,各得 120px
- item3 分配 1/5,得 60px
各子项最终宽度为:
- item1 = 0%(0px) + 120px = 120px
- item2 = auto(100px) + 120px = 220px
- item3 = 200px + 60px = 260px