详解 Flex 布局
前言:
FlexBox不仅在前端中应用广泛,同时在移动端也占有非常重要的地位,比如 iOS 中的UIStackView,Facebook 的 Yoga 库;微信小程序和 RN 都支持这种布局方式。各大浏览器对 FlexBox 支持比较完善,尤其对于移 Web,iOS 和 Android 在很早的版本中就支持了这种布局。所有我建议无论是移动端,还是泛前端的同学都应该学习一下这种布局方式。
image.png
备注:FlexBox 布局可以通过 flex-direction 来控制 flex-item 的布局方向
概念
需要解释几个概念:
flex-container:布局容器,使用 display:flex 的标签;
flex-item: 容器中的直接子元素;
main-axis:主轴,布局方向为 row 或者 row-reverse 时它是水平方向。布局方向为 column 或者 column-reverse 时它是垂直方向。
cross-axis: 纵轴,与主轴垂直的轴;
main-start: 主轴的起点,布局方向为 row 时它的起点在左侧,row-reverse 为右侧。布局方向为 column 时起点在顶部,column-reverse 时起点为底部。
main-end: 主轴结束的点,与 main-start 相反;
cross-start: 纵轴的起点;
cross-end:纵轴的结束点,与 cross-start 相反
1. flex-direction:
- flex items 默认都是沿main axis(主轴) 从 main start 开始向 main end 排布
- flex-direction决定了 main axis(主轴) 方向, 有四个取值:
row(默认):从水平方向的左侧开始布局;
row-reverse:从水平方向的右侧开始布局;
column:从垂直方向的顶部开始布局;
column-reverse: 从垂直方向的底部开始布局;
image.png
2. justify-content :
决定了 flex items 在 main axis(主轴)上的对齐方式,主轴不一定是水平方向,不能把 justify-content 看做是控制水平方向的对齐方式。它主要有以下几个值:
flex-start(默认):与主轴的起始位置(main start)对齐;
flex-end:与主轴的结束位置(main end)对齐;
center:居中于主轴;
space-around: 每个 item 的间距相等, flex item 之间的距离相等, flex item 与main start 和 main end之间的距离是flex items 之间距离的一半;
space-evenly: 每个 item 的间距相等, flex item 之间的距离相等, flex item 与main start 和 main end之间的距离等于flex items 之间的距离;
space-between: 左右无边距, flex item 之间的距离相等,左右两边与 main start 和 main end 对齐;
image.png
3.align-items
flex-start:与纵轴的起始位置(cross start)对齐;
flex-end:与纵轴的结束位置(cross end)对齐;
center:居中与纵轴;
baseline:与基准线对齐;
stretch(默认):当flex items在cross axis方向上的size为auto时,会自动拉伸填充至flex container
image.png
4.flex-wrap
决定了flex container是多行还是单行
nowrap(默认):单行显示;
wrap:多行显示;
wrap-reverse:多行显示;
5.flex-flow
它是 flex-direction 和 flex-wrap 的简写,
比如 flex-flow: row nowrap 等价于
flex-direction : row
flex-wrap : nowrap。
6.align-content
决定了多行flex item 在 cross axie 方向上的对齐方式,用法和 justify-content 相似
strech(默认值):与align-items的 strech类似
fles-start: 与cross start 对齐
fles-end: 与cross end 对齐
center: 居中对齐
space-around: 每个 item 的间距相等, flex item 之间的距离相等, flex item 与cross start 和 cross end之间的距离是flex items 之间距离的一半;
space-evenly: 每个 item 的间距相等, flex item 之间的距离相等, flex item 与cross start 和 cross end之间的距离等于flex items 之间的距离;
space-between: 左右无边距, flex item 之间的距离相等,左右两边与 cross start 和 cross end 对齐;
image.png
7. order
决定了 flex items的排布顺序
- 可以设置任意整数(正整数 负整数 0), 数值越小排下越前面
- 默认值都是0
8. align-self
flex items 可以通过 align-self 覆盖 flex container设置的 align-items
auto(默认值): 遵循flex container的align-items设置
strech flex-start flex-end center baseline 效果跟align-items一致
9. flex-grow
决定了flex items 如何扩展,它的作用就是,当所有的 item 未占满容器的宽度时,item 该如何扩充自己以填满容器的剩余空间。理解这个属性前关键要理解剩余空间,在 flex 容器中,如果所有 item 的宽度和小于容器的宽度,那么容器的剩余空间等于容器宽度减去所有item宽度的和。
-
每个 item 的宽度为 150px,容器宽度为 600 px,剩余空间为 600 - 3*150 = 150px, 一图胜千言:
image.png -
如果给每个 item 设置 flex-grow 为 1,它表示每个 item 占用相同比例的剩余空间,这样每个 item 增加的宽度为 150 * 1/3 = 50px。最终效果变成:
image.png -
flex-grow 的默认值为 0,表示即使有剩余空间,item 也不会扩充。它不能为负数,但是可以为小数,如果上面的例子中,给每个 item 设置 flex-grow 为 0.2,这样每个 item 增加的宽度为 150 * 0.2 = 30px,最终还会有 60px 的剩余空间未被占用。
image.png
总之 flex-grow 的值可以理解成比例,总剩余空间可以看成 1,剩余空间会受 flex-basis 影响,下面会提到这个属性的使用。还有一点需要明确,item 增长会受 max-width 的影响,增长后的最大长度只能是 max-width。
9.flex-shrink
(收缩比例):占缺少空间的比例(item*shrink作为收缩比例),当所有的 item 的宽度和大于容器的宽度,就会出现容器空间不足的情况,这时可以通过缩放比例来缩放每个 item 的宽度。
-
假如每个 item 的宽度为 250px,容器宽度为 600 px,缺少空间为 600 - 3*250 = -150px, 一图胜千言:
image.png -
一旦出现空间不足,可以通过 flex-shrink 控制每个 item 是否要进行缩放,缩放的比例是多少。如果设置 flex-shrink:1,每个 item 将缩放同样的宽度,其值为 150 * 1/3 = 50px,效果如下:
image.png
flex-shrink 的默认值是 1,也就是说当空间不足的时候,item 会以同样的尺寸进行缩放。但是这个属性和 flex-grow 在极端的情况下表现并不相同,因为在缩小的过程中,不会把 item 的尺寸缩小到 0,它会受 min-content 的影响,也会受 min-width 的影响,缩到一定尺寸后它就不再进行缩放了。
10.flex-basis
用来设置 flex items 在 main axis方向上的base size
auto (默认):content取决于本身内容的size
决定flex items最终base size因素优先级由高到低
max-width\max-height\min-width\min-height
flex-basis
width\height