flex 布局在日常开发的过程中是非常常用的了,相较于传统的流式布局,flex可以更加灵活的设置布局内元素的排布和大小。通常我们可以使用flex布局做出以下的效果:
- 元素的水平排布
- 元素的水平/垂直居中
- 子元素宽度/高度的等分
开启flex布局
flex布局的开启方式很简单,使用display: flex 或者 display: inline-flex即可,其区别是,前者为“块级弹性盒子” 后者为 “行内弹性盒子” 即外层容器盒子是块级还是行内级。我们更加常用的还是块级弹性盒子 display: flex 。
术语
flex布局主要围绕两类盒子展开
1. 外层的容器盒子 flex-container
2. 内层的flex元素,即 flex-item
其中,flex-item不严格区分 行内/块 你只要把他当成是flex的子元素即可,其宽度width高度height默认都为auto,表现为包裹内容大小 (类似于行内元素的宽高为自动包裹内容)
主轴和交叉轴
- 主轴(main axis),默认横向,即从左到右,行内元素布局的方向, 子元素按照主轴的方向排列。
- 交叉轴 (cross axis),和主轴垂直的方向,默认从上到下,即块元素排布的方向
- 主轴和交叉轴的方向都可以设置
- mian-start为主轴的起点,main-end为主轴的终点,main-size为主轴长度
- cross-start为交叉轴七点,cross-end为交叉轴终点,cross-size为交叉轴的长度
弹性布局属性
我们通常使用弹性布局的属性来调整弹性盒子内部元素的排布和大小,其属性可以归为两类,一类是写在弹性盒子容器(flex container)上的属性,一类是写在子元素(flex-item)上的属性
flex-container 属性
flex-direction
flex-direction控制主轴的方向,其默认值为 row,即横向排列(以行的方向排列 )
- row横向(默认)
- row-reverse (横向 反转【交叉轴 方向不变】)
- column 列 向下
- column-reverse 列 向上
flex-wrap 包裹
flex-wrap 用来设置,当容器内的子元素超出容器的范围后,是否换行
1. nowrap 不换行 (默认值),默认情况下,flex-item的flex-shrink属性为1,当子元素的宽度超出容器宽度时,会自动缩小以保证子元素宽度不超出容器宽度。所以在flex布局中,设置的width和flex-item的最终宽度并不一定一致。
2. wrap 换行,即超出容器宽度会自动换行显示
3. wrap-reverse 换行,但是超出宽度后会向反方向换行
flex-flow 简写属性
flex-flow是flex-direction和flex-wrap的简写属性,如:
flex-flow: row nowrap;
表示主轴横向,不换行。
justify-content 主轴对齐
justify-content 表示子元素沿主轴方向对齐的方式,其属性值如下:
-
Flex-start: 默认 沿着主轴开始的地方对齐 从main-start开始对齐
-
Flex-end: 从主轴结束的方向开始对齐 与main-end开始对齐
-
center: 居中对齐
-
Space-between 靠两边 中间均匀分布 先放两边
-
Space-around 等分 其中两遍距离main-start main-end的距离是 flex item之间距离的一半
-
Space-evenly 等分 所有距离都是等分 包括两遍和中间的 都是等分 (evenly均分)
align-items 交叉轴单行对齐
align-items 决定了,在单行元素的情况,如flex-wrap: nowrap 或者 元素总长度不超出容器的情况下,元素在交叉轴上的对齐方式
1. stretch 占满整个交叉轴,可以理解为fill-available, 类比块元素在width:auto的默认情况下,会沾满整个宽度一样
2. normal 默认,效果和stretch一样,但是要注意,如果flex-item显式设置了高度/宽度,则在normal/stretch的情况下也无法达到fill-available的效果
3. Flex-start 在cross-start开始对齐
4. Flex-end 在cross-end开始对齐
5. center 剧中对齐,这也是实现水平/垂直居中的方法
6. baseline 根据基线对齐
说到基线baseline你也许会想到vertical-align的baseline默认值,但是这里和vertical-align不同的是:
vertical-align如果是行内块或者是替换元素,如果有文本则基线为最后一行文本的基线,无文本则是元素底边
而align-items的baseline有所不同,如果flex-item存在文本,则以第一行文本的基线作为item的基线,如果不存在文本,则使用元素的底边,这里需要区分。
align-content 多行时交叉轴对齐
align-content也是交叉轴对齐,与align-items不同的是,align-content在元素发生换行时生效,决定多行元素在交叉轴上如何排布,其支持的属性和justify-content类似,包括
1. flex-start
2. flex-end
3. center
4. space-between
5.space-around
6.space-evenly
区别在于,align-conten支持stretch属性,也是其默认值,即填满交叉轴 fill-available
需要注意的是,如果显式设置了高度,则无法实现fill-available的效果
flex-item 属性
flex-item属性通常写在子元素上面,用来单独控制某个子元素自己的排布方式,大小等
order 排布顺序
order默认为0,子元素设置order后,会根据order的大小调整元素排布的先后顺序。设置order后,flex-item的排列顺可能和html结构中的元素顺序不一致
align-self
align-self 设置某个元素自己在单行的情况下,在交叉轴上的对齐方式,其覆盖align-items,可选的属性值和align-items一样。
flex-grow
flex-grow 在子元素宽度不足容器宽度时 (准确的说应该是flex-basis)生效,其值决定子元素的增长, 其默认值为0,即不增长。
当设置flex-grow >= 1 时,会根据一行中子元素的flex-grow,按照比例分配剩余的宽度
当设置flex-grow < 1 时,会直接使用剩余宽度* flex-grow
如上 (1)所示,当子元素宽度刚好等于 或者大于容器宽度,则flex-grow不生效
(2) 当子元素占不满容器时,按照比例分配剩余空间,由于item2 item3 的grow都为0,所以设置为1的item1会分配所有剩余空间
(3) 中,三个子元素占不满容器但是都设置了flex-grow: 1 则平均分配,每个item分配到1/3的剩余空间
这个例子中,由于flex-grow<1 不按照比例分配,而是直接用flex-grow * 剩余宽度
由于 0.1 + 0.2 + 0.1 < 1 所以剩余空间不能被分配完,导致虽然设置了flex-grow,但是还是有剩余空间
flex-shrink
flex-shrink 默认值为1 在子元素超出容器的限制时生效,其值决定了子元素在超出容器时缩小的长度。
flex-shink默认为1,当超出容器时,每个容器都会收缩 超出宽度/子元素数量 个像素的宽度
当shrink的值 >=1 时,按照比例收缩 即每个容器收缩 超出宽度 * (当前元素shrink/所有元素shrink)
当shrink < 1 时,直接收缩 超出宽度*shrink的宽度,所以当一行元素的shrink都是<1 并且总和加起来不够1 则还是会超出容器范围
flex-basis
flex-basis和width看上去作用差不多,但是存在区别
flex-basis 是 主轴上的长度基准,所以flex-basis不一定和width有关 也可能和height有关 (主轴方向为column时)
同时,flex-basis 的优先级比height/width高,在未设置basis属性并且设置height/width属性时,会默认将height/width值赋给basis
在flex布局中,你会发现width/height很多时候和实际展示的宽高并不符合,就是因为其本质上设置的是basis的值,而basis只是在主轴上的一个基准,最终宽高还会受到grow shrink的影响
在使用flex布局时,我们最好使用basis来代替width/height
flex 复合属性
flex是符合属性,可以同时设置 grow shrink basis,其规则如下
1. 如果flex只设置一个属性
如果为数字类型,则设置的是flex-grow
如果为长度类型,则设置的是flex-basis
2. 如果flex设置两个属性
第一个属性必须为数字类型,设置flex-grow
第二个值 可以为 (1) 数字类型,设置flex-shrink (2) 长度 设置flex-basis
3. 如果flex设置三个属性
第一个值必须为数字 设置flex-grow
第二个值必须为数字 设置flex-shrink
第三个值必须为长度 设置flex-basis