3、元素如何弹性伸缩应对
当flex-wrap: nowrap;
不折行时,容器宽度有剩余/不够分,弹性元素们该怎么“弹性”地伸缩应对?
这里针对上面两种场景,引入两个属性(需应用在弹性元素上)
flex-shrink
:缩小比例(容器宽度<元素总宽度时如何收缩)flex-grow
:放大比例(容器宽度>元素总宽度时如何伸展)
1. flex-shrink: 缩小比例
来看下如下场景,弹性容器#container
宽度是200px,一共有三个弹性元素,宽度分别是50px、100px、120px。在不折行的状况下,此时容器宽度是明显不够分配的。
实际上,flex-shrink
默认为1,也就是当不够分配时,元素都将等比例缩小,占满整个宽度,以下图。
#container {
display: flex; flex-wrap: nowrap; }
元素收缩的计算方法
真的是等比缩小(每一个元素各减去70/3的宽度)吗?这里稍微深究一下它的收缩计算方法。
- 弹性元素1:50px→37.03px
- 弹性元素2:100px→74.08px
- 弹性元素3:120px→88.89px
先抛结论:flex-shrink: 1
并不是严格等比缩小,它还会考虑弹性元素自己的大小。
- 容器剩余宽度:
-70px
- 缩小因子的分母:
1*50 + 1*100 + 1*120 = 270
(1为各元素flex-shrink的值) - 元素1的缩小因子:
1*50/270
- 元素1的缩小宽度为缩小因子乘于容器剩余宽度:
1*50/270 * (-70)
- 元素1最后则缩小为:
50px + (1*50/270 *(-70)) = 37.03px
加入弹性元素自己大小做为计算方法的考虑因素,主要是为了不将一些自己宽度较小的元素在收缩以后宽度变为0的状况出现。
2. flex-grow: 放大比例
一样,弹性容器#container
宽度是200px,但此时只有两个弹性元素,宽度分别是50px、100px。此时容器宽度是有剩余的。
那么剩余的宽度该怎样分配?而flex-grow
则决定了要不要分配以及各个分配多少。
(1)在flex布局中,容器剩余宽度默认是不进行分配的,也就是全部弹性元素的flex-grow
都为0。
(2)经过指定flex-grow
为大于零的值,实现容器剩余宽度的分配比例设置。
元素放大的计算方法
放大的计算方法并无与缩小同样,将元素大小归入考虑。
仅仅按flex-grow
声明的份数算出每一个需分配多少,叠加到原来的尺寸上。
- 容器剩余宽度:
50px
- 分红每份:
50px / (3+2) = 10px
- 元素1放大为:
50px + 3 * 10 = 80px
无多余宽度时,flex-grow无效
下图中,弹性容器的宽度正好等于元素宽度总和,无多余宽度,此时不管flex-grow
是什么值都不会生效。
同理,对于flex-shrink
,在容器宽度有剩余时也是不会生效的。所以这两个属性是针对两种不一样场景的互斥属性。
4、弹性处理与刚性尺寸
在进行弹性处理之余,其实有些场景咱们更但愿元素尺寸固定,不须要进行弹性调整。设置元素尺寸除了width和height之外,flex还提供了一个flex-basis
属性。
flex-basis
设置的是元素在主轴上的初始尺寸,所谓的初始尺寸就是元素在flex-grow
和flex-shrink
生效前的尺寸。
1. 与width/height的区别
首先以width为例进行比较。看下下面的例子。#container {display:flex;}
。
<div id="container"> <div>11111</div> <div>22222</div> </div>
(1) 二者都为0
- width: 0 —— 彻底没显示
- flex-basis: 0 —— 根据内容撑开宽度
(2) 二者非0
- width: 非0;
- flex-basis: 非0
—— 数值相同时二者等效
—— 同时设置,flex-basis优先级高
(3) flex-basis为auto
flex-basis为auto时,如设置了width则元素尺寸由width决定;没有设置则由内容决定
(4) flex-basis == 主轴上的尺寸 != width
- 将主轴方向改成:上→下
- 此时主轴上的尺寸是元素的height
- flex-basis == height
2. 经常使用的复合属性 flex
这个属性应该是最容易迷糊的一个,下面揭开它的真面目。
flex = flex-grow + flex-shrink + flex-basis
复合属性,前面说的三个属性的简写。
一些简写
flex: 1
=flex: 1 1 0%
flex: 2
=flex: 2 1 0%
flex: auto
=flex: 1 1 auto;
flex: none
=flex: 0 0 auto;
// 经常使用于固定尺寸 不伸缩
flex:1 和 flex:auto 的区别
其实能够归结于flex-basis:0
和flex-basis:auto
的区别。
flex-basis
是指定初始尺寸,当设置为0时(绝对弹性元素),此时至关于告诉flex-grow
和flex-shrink
在伸缩的时候不须要考虑个人尺寸;相反当设置为auto
时(相对弹性元素),此时则须要在伸缩时将元素尺寸归入考虑。
所以从下图(转自W3C)能够看到绝对弹性元素若是flex-grow
值是同样的话,那么他们的尺寸必定是同样的。
5、容器内如何对齐
前面讲完了元素大小关系以后,下面是另一个重要议题——如何对齐。能够发现上面的全部属性都是围绕主轴进行设置的,但在对齐方面则不得不加入做用于交叉轴上。须要注意的是这些对齐属性都是做用于容器上。
1. 主轴上的对齐方式
justify-content
2. 交叉轴上的对齐方式
主轴上比较好理解,重点是交叉轴上。由于交叉轴上存在单行和多行两种状况。
交叉轴上的单行对齐
align-items
默认值是stretch
,当元素没有设置具体尺寸时会将容器在交叉轴方向撑满。
当align-items
不为stretch
时,此时除了对齐方式会改变以外,元素在交叉轴方向上的尺寸将由内容或自身尺寸(宽高)决定。
注意,交叉轴不必定是从上往下,这点再次强调也不为过。
交叉轴上的多行对齐
还记得能够经过flex-wrap: wrap
使得元素在一行放不下时进行换行。在这种场景下就会在交叉轴上出现多行,多行状况下,flex布局提供了align-content
属性设置对齐。
align-content
与align-items
比较相似,同时也比较容易迷糊。下面会将二者对比着来看它们的异同。
首先明确一点:align-content
只对多行元素有效,会以多行做为总体进行对齐,容器必须开启换行。
align-content: stretch | flex-start | flex-end | center | space-between | space-around align-items: stretch | flex-start | flex-end | center | baseline
在属性值上,align-content
比align-items
多了两个值:space-between
和space-around
。
align-content与align-items异同对比
与align-items
同样,align-content:
默认值也是stretch
。二者同时都为stretch
时,毫无悬念全部元素都是撑满交叉轴。
#container { align-items: stretch; align-content: stretch; }
当咱们将align-items改成flex-start
或者给弹性元素设置一个具体高度,此时效果是行与行之间造成了间距。
#container {
align-items: flex-start;
align-content: stretch;
}
/*或者*/ #container { align-content: stretch; } #container > div { height: 30px; }
为何?由于align-content
会以整行为单位,此时会将整行进行拉伸占满交叉轴;而align-items
设置了高度或者顶对齐,在不能用高度进行拉伸的状况下,选择了用间距。
尝试把align-content
设置为顶对齐,此时以行为单位,总体高度经过内容撑开。
而align-items
仅仅管一行,所以在只有第一个元素设置了高度的状况下,第一行的其余元素遵循align-items: stretch
也被拉伸到了50px。而第二行则保持高度不变。
#container {
align-items: stretch;
align-content: flex-start;
}
#container > div:first-child {
height: 50px; }
二者的区别仍是不明显?来看下面这个例子。
这里仅对第二个元素的高度进行设置,其余元素高度则仍保持内容撑开。
以第一个图为例,会发现align-content
会将全部行进行顶对齐,而后第一行因为第二个元素设置了较高的高度,所以体现出了底对齐。
二者差别总结:
- 二者“做用域”不一样
- align-content管全局(全部行视为总体)
- align-items管单行
可否更灵活地设置交叉轴对齐
除了在容器上设置交叉轴对齐,还能够经过align-self
单独对某个元素设置交叉轴对齐方式。
- 值与
align-items
相同 - 可覆盖容器的
align-items
属性 - 默认值为
auto
,表示继承父元素的align-items
属性
#container {
display: flex; align-items: flex-start; } #container > div:first-child { align-self: stretch; } #container > div:nth-child(3) { align-self: center; } #container > div:nth-child(4) { align-self: flex-end; }
6、其余
order:更优雅地调整元素顺序
#container > div:first-child {
order: 2; } #container > div:nth-child(2) { order: 4; } #container > div:nth-child(3) { order: 1; } #container > div:nth-child(4) { order: 3; }
order:可设置元素之间的排列顺序
- 数值越小,越靠前,默认为0
- 值相同时,以dom中元素排列为准