共计 5284 个字符,预计需要花费 14 分钟才能阅读完成。
一、Flex 布局简介
Flex 是 Flexible Box 的缩写,意为 ”弹性布局“,用来为盒状模型提供最大的灵活性。
任何一个容器 都可以指定为 Flex 布局,也就是说,行内元素也可以设置成 Flex 布局。
// 将块级元素 div 设置为 flex 布局
div {display: flex;}
// 将行内元素 span 设置为 flex 布局
span {display: flex;}
采用 Flex 布局的元素,称为 Flex 容器 (flex container),简称 ” 容器 “。它的 所有子元素自动成为容器成员 ,称为 Flex 项目(flex item),简称 ” 项目“。
二、Flex 布局的默认特性
默认情况下,容器中的所有子元素都将进行水平排列 ,类似于强制进行了一个左浮动,所以 容器子元素的 float 和 clear 属性会失效 。同时, 容器中的子元素的对齐方式将不受 vertical-align 控制,即vertical-align 也会失效。
<style>
#main{
width:800px;
height:300px;
display:flex;
font-size: 20px;
background: red;
}
</style>
<div id="main">
<div style="background-color:coral;" class="item-1"> 红色 </div>
<div style="background-color:lightblue;" class="item-2"> 蓝色 </div>
<div style="background-color:lightgreen;" class="item-3"> 带有更多内容的绿色啊 </div>
</div>
① 在 没有给容器设置垂直方向对齐方式 同时 容器子元素也没有设置高度 ,那么 容器子元素的高度是和容器的高度是一样的,如上,容器中所有的子元素的高度都会变为 300px。
② 默认情况下,容器下的子元素的宽度是不会自动放大的 ,即 默认以元素自身的实际宽度显示。如图所示:
③ 默认情况下,容器下的子元素的宽度是可以缩小的 ,当容器中所有子元素的宽度之和超过了容器的宽度, 默认不会换行显示 ,那么就需要 缩小容器子元素的宽度以保证容器能够容纳下所有的子元素 。但容器子元素的宽度并不是无限缩小的,即 缩小到不能缩小为止。
.item-1 {width: 200px;}
.item-2 {width: 8800px;}
.item-3 {width: 8800px;}
比如上面,item2、item3 宽度设置成了 8800px,容器中所有子元素的宽度和为 17800px,远远超出了容器的宽度 800px,所以 容器中的所有子元素必须按比例压缩,item1 元素的宽度应变为200 – 191.01 = 8.99px,而item1 最小被压缩为存放一个字所需要的宽度,即刚好等于字体的大小,即 20px,所以 item1 的宽度将变为 20px。
④ 默认情况下,容器中的子元素可以被压缩到最小为止,但是 当压缩到最小后仍然放不下所有的子元素 ,那么 子元素就会被放到容器的外面 。
⑤ 如果给容器添加一个垂直方向的对齐方式,那么容器中所有子元素的高度将变为实际的高度, 不会与容器等高。
#main{
width:800px;
height:300px;
display:flex;
font-size: 20px;
background: red;
align-items: flex-start;/* 添加垂直方向对齐方式 */
}
三、容器属性设置
容器默认存在两根轴:水平的主轴 和 垂直的交叉轴 。主要就是设置 容器的主轴方向 、 超过容器后是否换行显示 、 水平对齐方式 、 垂直对齐方式 。
① flex-direction : 用于 设置主轴的方向 ,默认值为row,即 容器中所有子元素水平排列 。
column: 表示 容器中所有子元素垂直排列 。
row-reverse: 表示 反转容器中所有子元素的顺序 ,并且起点靠右,即 靠右对齐 。
column-reverse: 表示 反转容器中所有子元素的顺序 ,并且起点靠下,即 靠容器底部对齐。
② flex-wrap: 用于 设置容器中子元素放不下的时候是否换行 。默认值为nowrap,即 不换行,即使放不下也不换行。
wrap : 表示 可以换行 ,当设置为 wrap 可以换行的时候, 容器中的元素就不会被压缩,而是采用换行显示。
#main {
width:800px;
height:300px;
display:flex;
background: red;
flex-wrap: wrap; /* 放不下的时候可以换行 */
font-size: 20px;
}
.item-1 {width: 300px;}
.item-2 {width: 300px;}
.item-3 {width: 300px;}
wrap-reverse : 表示 换行显示之后对行排列顺序进行反转。
wrap:
wrap-reverse:
③ flex-flow: 是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为row nowrap,即主轴为水平方向,不换行。
④ justify-content: 用于设置 主轴方向 的对齐方式。
⑤ align-items: 用于设置项目在 交叉轴 (非主轴) 上对齐方式。
四、容器中元素 (项目) 属性设置
① order: 用于 设置容器元素的排列顺序 , 默认值为 0 ,数值越小,排列越靠前。
.item-2 {order: -1; /* 将 item- 2 的 order 设置为 -1,可以让 item- 2 排在前面 */}
② flex-grow: 用于 设置容器元素的放大比例 , 默认值为 0 ,即 如果存在剩余空间,也不放大。
③ flex-shrink: 用于 设置容器元素的缩小比例 , 默认值为 1 ,即 如果空间不足,该项目将缩小。
④ flex-basis: 用于 设置容器元素占的大小 , 默认值为 auto,即 与容器元素的实际大小一致 。 进行缩放的时候会根据该值来进行计算是否有多余的缩放空间。
⑤ flex: 是 flex-grow、flex-shrink、flex-basis 的简写,默认值为 0 1 auto,即 不可放大 、 可缩小 、 大小与容器元素大小一致,后两个属性可选。
.item-2 {flex: 0 1 auto;/* 注意三个值之间是空格二不是逗号 */}
⑥ align-self: 用于 单独设置某个容器元素的对齐方式 , 默认值为 auto,表示 继承父元素的对齐方式。
.item-2 {align-self: center;/* 单独设置 item- 2 居中对齐 */}
五、felx:1 和 flex: auto 的区别
从上面可知,flex 的默认值为 0 1 auto。flex 的值比较灵活,可以设置很多种值,如:
① none: 此时等于 0 0 auto。
.item {flex: none; // 值为 none}
// 等价于
.item {
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
}
② auto: 此时等于 1 1 auto。
.item {flex: auto; // 值为 auto}
// 等价于
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
③ 一个非负数字 : 此时 这个非负数字指的是 flex-grow 的值,flex-shrink 采用默认值 1,但是flex-basis 值为 0%,如:
.item {flex: 1; // 值为一个非负数字}
// 等价于
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%; /* 这里比较特殊为 0%*/
}
④ 取值为两个非负数字: 此时分别代表的是 flex-grow 和 flex-shrink 的值,flex-basis 取值为 0%。
.item {flex: 6 8; // 值为两个非负数字}
// 等价于
.item {
flex-grow: 6;
flex-shrink: 8;
flex-basis: 0%; /* 这里比较特殊为 0%*/
}
⑤ 一个长度或百分比 : 此时 这个值为 flex-basis 的值,flex-grow 取值为 1,flex-shrink 取值为 1
.item {flex: 200px; // 值为一个像素值}
// 等价于
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 200px;
}
.item {flex: 100%; // 值为一个百分数}
// 等价于
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 100%;
}
需要注意的是,如果 flex-basis 设置为百分比,那么 其相对的是容器的大小的百分比 , 而不是自身的大小的百分比。
从上可以看到,当 flex 的值为 none 或者 auto 或者 不设置 的时候,flex-basis 的值才是 auto;其他情况如 flex 的值为数字 的时候,flex-basis 的值则为 0%。
所以 flex: 1 和 flex: auto 的区别就是,flex-basis 的值不同,flex:1 的时候 flex-basis 值为 0%;flex: auto 的时候,flex-basis 的值为 auto。
六、容器元素放大或缩小值计算
① 放大的情况
主要就是根据 flex-basis 的值计算出容器是否有剩余空间,如果 有剩余空间 ,并且 该容器中某个子元素是可以放大的 ,那么用该子元素的flex-grow 值比上容器中所有子元素的 flex-grow 值之和计算出该容器子元素的放大系数,然后 乘以剩余空间的大小 即是该容器子元素需要放大的像素值。
#main{
width:800px;
height:300px;
display:flex;
background: red;
font-size: 20px;
}
.item-1 {
width: 200px;
flex: 2 1 auto;
}
.item-2 {
width: 200px;
flex: 3 1 10%;/* 这里 flex-basis 值相当于是 80px*/
}
.item-3 {
width: 100px;
flex: 0 1 220px;
}
itme- 1 的 flex-basis 为 auto,所以值和元素本身大小一致,即 200px;
item- 2 的 flex-basis 为 10%,其相对的是容器自身的大小,即800px * 10% = 80px;
item- 3 的 flex-basis 为 设置的 220px,这里需要注意的是,虽然 width 设置的为 100px,但是 width 不会其作用,仍然会以 flex-basis 为基准 。
首先根据 flex-basis 计算出剩余空间 = 800px – (200px + 80px + 220px) = 300px;
由于剩余空间为 300px > 0,所以 容器中的子元素可以放大 ,由于 item- 3 的 flex-grow 值为 0,所以 item- 3 不会放大, 仍然以 220px 显示 。
item- 1 的放大值 = 2 / (2 + 3) * 300px = 120px;
item- 2 的放大值 = 3 / (2 + 3) * 300px = 180px;
所以,最终 item- 1 的大小 = 200px + 120px = 320px;
item- 2 的大小 = 80px + 180px = 260px;
item- 3 的大小 = 220px;
② 缩小的情况
缩小的情况也是先根据 flex-basis 的值计算出容器超出容器多少空间,但是其不是简单的根据 flex-shrink 的值计算出缩放比例,而是 根据容器中某个元素的 flex-basis 值乘以 flex-shrink 的值占容器中所有子元素的 flex-basis 乘以 flex-shrink 的值之和来计算缩放比例的。
#main{
width:800px;
height:300px;
display:flex;
background: red;
font-size: 20px;
}
.item-1 {
width: 200px;
flex: 0 2 auto;
}
.item-2 {
width: 200px;
flex: 0 3 100%;/* 这里 flex-basis 值相当于是 800px*/
}
.item-3 {
width: 100px;
flex: 0 0 200px;
}
itme- 1 的 flex-basis 为 auto,所以值和元素本身大小一致,即 200px;
item- 2 的 flex-basis 为 100%,其相对的是容器自身的大小,即800px * 100% = 800px;
item- 3 的 flex-basis 为 设置的 200px,这里需要注意的是,虽然 width 设置的为 100px,但是 width 不会其作用,仍然会以 flex-basis 为基准 。
首先根据 flex-basis 计算出超出空间 = (200px + 800px + 200px) – 800px = 400px;
由于超出空间为 400px > 0,所以 容器中的子元素需要缩小 ,由于 item- 3 的 flex-shrink 值为 0,所以 item- 3 不会缩小, 仍然以 200px 显示 。
item- 1 的缩小值 = (2 200px / (2 200px + 3 800px + 0 200px)) * 400px = 57.14px;
item- 2 的放大值 = (3 800px / (2 200px + 3 800px + 0 200px)) * 400px = 342.86px;
所以,最终 item- 1 的大小 = 200px – 57.14px = 142.86px;
item- 2 的大小 = 800px – 342.86px = 457.14px;
item- 3 的大小 = 200px;