HTML

前言

前端布局的传统解决方案是基于盒状模型,依赖 display + position + float 方式来实现,灵活性较差。Flex 布局可以通过简单的属性灵活实现复杂的响应式布局。
当会Flex布局后,几乎所有布局都可以通过Flex解决。

Flex的基本概念

Flex 布局顾名思义弹性布局,意味着灵活。里面有两个概念,叫容器和轴。使用flex布局的元素称为容器(flex container),该容器里面所有的子元素称为项目(flex item)。
2021-05-08-21-05-39-007881.jpeg
容器有两根轴,分为主轴(main axis)和交叉轴(cross asix)。默认情况下,主轴是水平方向的,交叉轴是垂直方向的。容器里面的项目默认沿着主轴方向排列。
2021-05-08-21-05-39-147685.jpeg
Flex 属性分为两部分,一部分是作用在容器上的称为容器属性,另一部分是是作用于项目上的称为项目属性。

容器属性

1、display

  1. .container {
  2. display: flex | inline-flex;
  3. }

要使用flex布局,首先必须设置容器的display属性为flex或inline-flex, 块元素使用flex, 内联元素就使用inline-flex。指定flex后,项目的float、clear属性都将失效。
来看个最简单的例子

  1. <div class="container">
  2. <div class="item">flex item</div>
  3. <div class="item">flex item</div>
  4. <div class="item">flex item</div>
  5. </div>

外面的div是容器,里面有3个flex item,只需要外面的div的display属性设置为flex,该容器就成了flex布局。三个项目会沿着主轴方向依次排列。

  1. .container {
  2. display: flex;
  3. border: 1px black solid;
  4. width: 500px;
  5. }
  6. .item {
  7. width: 100px;
  8. height: 100px;
  9. background-color: paleturquoise;
  10. margin: 20px;
  11. }

下面就是flex布局的页面效果,3个项目沿着主轴水平排列在一行
2021-05-08-21-05-39-285629.png

2、flex-direction

flex-direction用于指定主轴的方向, 有四个值, 默认是row,水平方向。项目始终沿着主轴的方向排列,如果改变了flex-direction,项目的布局排列就会跟着发生变化。

  1. flex-direction: row|row-reverse|column|column-reverse;

来分别看下4个值对应的效果是咋样吧

  1. .container {
  2. flex-direction: row;
  3. }

row 表示主轴为水平方向,从左至右
2021-05-08-21-05-39-368440.png

  1. .container {
  2. flex-direction: row-reverse;
  3. }

row-reverse: 主轴为水平方向,从右到左(和row是相反的)
2021-05-08-21-05-39-474226.png

  1. .container {
  2. flex-direction: column ;
  3. }

column: 主轴为垂直方向,从上至下
2021-05-08-21-05-39-588542.png

  1. .container {
  2. flex-direction: column-reverse;
  3. }

column-reverse 主轴为垂直方向,从下往上
2021-05-08-21-05-39-710311.png

3、flex-wrap

flex-wrap 用于确定项目元素是否换行展示, 当所有 item 在主轴(假设主轴为水平方向 flex-direction:row)的宽度之和超过容器的大小,可以用flex-wrap决定是否换行显示。

  1. flex-wrap: no-wrap|wrap|wrap-reverse;

默认值为no-wrap,表示不换行,当项目的宽度超出时,会自动缩小item的宽度,确保他们都显示在一行。
将容器的宽度设置为200px, 三个item的宽度之和是300px,超过了容器的宽度

  1. .container {
  2. width: 200px;
  3. flex-wrap: no-wrap;
  4. }

2021-05-08-21-05-39-832427.png
wrap 就是换行显示,当子项目的宽度之和超出父容器宽度时,就会另起一行。

  1. .container {
  2. flex-wrap: wrap;
  3. }

2021-05-08-21-05-39-943131.png

  1. .container {
  2. flex-wrap: wrap-reverse;
  3. }

wrap-reverse 表示换行,方向与wrap相反,后面的元素在上面。
2021-05-08-21-05-40-065854.png

4、flex-flow

flex-flow 就是 flex-direction 与 flex-wrap 的缩写, 两个值可以用flex-flow 来表示

  1. .container {
  2. flex-flow: column wrap;
  3. }

5、justify-content

justify-content 用于指定item在主轴对齐方式, item可沿着主轴开始方向(flex-start)对齐、结束方向(flex-end)对齐、居中对齐(center)、两端对齐(space-between)、两侧对齐(space-around)。
沿主轴开始方向对齐

  1. .container {
  2. justify-content: flex-start; //默认值
  3. }

2021-05-08-21-05-40-132709.png
沿主轴结束方向对齐

  1. .container {
  2. justify-content: flex-end;
  3. }

2021-05-08-21-05-40-254455.png
居中对齐

  1. .container {
  2. justify-content: center;
  3. }

居中对齐后,最左侧和右侧两边流出的空间是相等的
2021-05-08-21-05-40-369208.png

  1. .container {
  2. justify-content: space-between;
  3. }

两端对齐是指两两项目之间的间隔是相等的
2021-05-08-21-05-40-479166.png

  1. .container {
  2. justify-content: space-around;
  3. }

两侧对齐是指单个项目左右两侧的间隔是相等的,所以项目边缘的空隙是两个项目之前间隔的一半
2021-05-08-21-05-40-630441.png

6、align-item

align-item 定义了项目在交叉轴方向的对齐方式,同样有沿轴的开始方向(flex-start)对齐,结束方向对齐(flex-end)对齐和居中对齐(center)baseline和stretch。

  1. align-item:flex-start|flex-end|center|baseline|stretch

stretch 为默认值,如果项目没有设置高度或者高度为auto,那么项目的高度将被拉伸到占满整个容器的高度。前面的图因为给3个项目设置了相同的高度,所以stretch并不会生效。现在把项目的高度去掉,显式指定 align-items 为 stretch 。

  1. .container {
  2. align-items: stretch;
  3. height: 200px;
  4. }
  5. .item {
  6. width: 100px;
  7. background-color: paleturquoise;
  8. margin: 0 20px;
  9. }

2021-05-08-21-05-40-721347.png

  1. .container {
  2. align-items: center;
  3. justify-content: center;
  4. }

当给项目设置主轴和交叉轴的对齐方式都是center时,那么项目就可以同时在水平和垂直方向居中了。flex-end 和 flex-start 就不介绍了,自己试验看下效果就行。
2021-05-08-21-05-40-815572.png

7、align-content

align-content 是指项目如果有多行时,在交叉轴的对齐方式

  1. .container {
  2. align-content: flex-start | flex-end | center | space-between | space-around | stretch;
  3. }

这些属性值在前面都出现过,意义是一样的。可以通过设置不同的值来看效果
总结一下容器下的几个属性
容器总共7个属性,除了display就6个,flex-flow 是 flex-drection 和 flex-wrap 的组合, 所以最后其实要记住的属性就5个。flex-drection 指定主轴和交叉轴。flex-wrap 用于项目超出父容器时是否要换行,justfiy-content 是主轴的对齐方式,align-items 和 align-content 是项目在交叉轴方向的对齐方式,align-content只在多行时才生效。

项目属性

flex item 项目也有5个属性

  • flex
    • flex-grow
    • flex-shrink
    • flex-basis
  • order
  • align-self

这5个属性是设置在项目中的属性, 当所有项目的宽度或高度之和在主轴或交叉轴方向还有很多剩余空间或者空间不足以装载这些子项目时,可以用这些属性通过拉伸或者压缩子项目来控制子项目,使之灵活实现弹性布局。

剩余空间

什么是剩余空间呢?假设容器的宽度是400px, A、B、C3个子项目的宽度都100px, 他们的内外边距都为0,那么容器主轴方向的剩余空间是400-300=100px。
2021-05-08-21-05-40-973005.png
这剩余出来的100px空间可以通过拉伸项目来填满。

  1. <div class="container">
  2. <div class="item a">
  3. <p>A</p>
  4. </div>
  5. <div class="item b">
  6. <p>B</p>
  7. </div>
  8. <div class="item c">
  9. <p>C</p>
  10. </div>
  11. </div>
  1. .container {
  2. background-color: #eee;
  3. display: flex;
  4. width:400px;
  5. height: 200px;
  6. text-align: center;
  7. color: #666;
  8. }
  9. .item {
  10. height: 100px;
  11. }
  12. .a {
  13. width: 100px;
  14. background-color: #61dafb;
  15. }
  16. .b {
  17. width: 100px;
  18. background-color: #f5fb61;
  19. }
  20. .c {
  21. width: 100px;
  22. background-color: #fb6c61;
  23. }

flex-grow

flex-grow 的默认值为0,子项目不进行任何比例的拉伸,如果将3个子项目的flex-grow属性都设置为1, 那么他们将按照1:1:1的比例来分配剩余的100px空间。每个子项目的宽度就有133.3px了。

  1. .item {
  2. flex-grow: 1;
  3. }

2021-05-08-21-05-41-084580.png
如果只给A项目设置flex-grow的属性为1,其它两个默认为0, 他们的比例就是1:0:0,意味着所有的剩余空间都给了A,A就有200px了。

  1. .a {
  2. width: 100px;
  3. background-color: #61dafb;
  4. flex-grow: 1;
  5. }

2021-05-08-21-05-41-191460.png
如果A、B、C三个项目的flex-grow 分别设置为 1:2:3, 那么他们将按改比例来瓜分剩余空间啊,就像下面这样
2021-05-08-21-05-41-285305.png
如果容器压根就没有剩余空间,那么即使设置了flex-grow不会生效

flex-shrink

当容器的空间不足以容纳子项目的空间时,要么选择换行,要么选择将项目进行压缩。flex-shrink 的默认值为1。
将容器的宽度设置为200px, 3个子项目的宽度都是100px, 这时容器的宽度不足,默认情况下3个项目的宽度都进行等比例压缩,变成了66.67px。
2021-05-08-21-05-41-377076.png
如果不希望被压缩,可以选择换行,只要设置 flex-wrap 属性为 wrap 就好。
2021-05-08-21-05-41-502739.png
为什么C的长度是A和B的长度之和呢?因为 C 换行后独占一行,相当于在第二根主轴方向只有它,这时候又设置了flex-grow的值,所有它会把所有剩余空间全部占满。
如果选择不换行对项目进行压缩的话,就可以使用flex-shrink 属性,数值越大,压缩越多。具体压缩多少呢?这个要看溢出的空间有多少。flex-shrink 为0时不压缩。
如果容器还有剩余空间,设置flex-shrink也是无效的。

flex-basis

flex-basis 表示项目在主轴的空间(flex-direction为row时就是项目的宽度),默认值是auto,即项目本来的宽度。计算主轴还有多少剩余空间就是用来这个属性来计算。
项目的实际宽度有个优先级:max-width/min-width > flex-basis > width > box, 意味着这些属性同时存在时,优先取 max-width和min-width。
flex-grow, flex-shrink 和 flex-basis 可以用一个flex属性将三个值组合在一起。

  1. .item {
  2. flex:0;
  3. }
  4. // 等价于
  5. .item {
  6. flex-grow: 0;
  7. flex-shrink: 1;
  8. flex-basis: 0%;
  9. }
  10. .item {
  11. flex:1;
  12. }
  13. // 等价于
  14. .item {
  15. flex-grow: 1;
  16. flex-shrink: 1;
  17. flex-basis: 0%;
  18. }

flex的属性基本总结的思维导图
2021-05-08-21-05-41-796467.png