flex弹性布局

973 阅读9分钟

概述

css-flexbox-poster.png

初识

弹性盒子是一种用于按行或按列布局容器的一维布局方法。容器可以膨胀以填充额外空间,收缩以适应更小的空间

一行在不同分辨率下可能表现不同

image.png

一列中可能让某一个更长一些

image.png

主轴与交叉轴

image.png

注意点:

  • 主轴与交叉轴并不是固定不变的,主轴可以是纵向的,交叉轴也可以是横向的,但是彼此是交叉的

flex容器与flex子项

子项和容器的属性是独立的,使用的时候不要混淆了

image.png

改变轴方向

image.png

  • 默认情况下水平方向排列,起点在左,终点在右
image.png
  • flex-direction:row-reverse 主轴方向起点终点位置互换,起点在右,终点在左
image.png
  • flex-direction: column; 主轴方向从水平变成垂直方向,起点在上(交叉轴变成了横向),终点在下
image.png
  • flex-direction: column-reverse 主轴方向从水平变成垂直方向,起点在下(交叉轴变成了横向),终点在上
image.png

换行与缩写

默认情况下是不换行

image.png

弹性布局的特点:

  1. 即使内部容器的宽度超出容器,也不会超出容器(除非内部容器缩小到最小宽度以下),弹性容器内部的容器会自动进行缩放以适应容器的宽度,如下图所示
image.png
  1. 如果弹性盒子内部的容器没有设置宽度,那么默认它的宽度就是内容的宽度(类似浮动的特性),如果弹性盒子内部的容器没有设置高度,那么高度会自适应到和弹性盒子高度一致
  • 加上flex-wrap: wrap;换行后
image.png

但是效果并不是我们想象的那样,第二行紧贴着第一行,它的逻辑是这样:弹性盒子知道内部的容器被分成2行,因此就将盒子分成一半一半,第一行占一半的上面,第二行占另外一行的上面

image.png

如果换行换成3行也是类似的道理,首先将弹性盒子分成三份,每一行都占那一份的最上面

以上情况出现的前提是给弹性盒子设置了高度

如果不给弹性盒子设置高度,那么它里面的子容器换行就变成下面这样,因为没有了高度,它就会自适应按顺序的排列

image.png
  • 加上flex-wrap: wrap-reverse;后,弹性盒子内部的容器就会出现反向折行(基本很难用到)
image.png
  • 如果垂直方向折行
flex-direction: column;
flex-wrap: wrap;

就是这样的效果

image.png

弹性布局是一维布局方式比较适合单行单列的布局,不太适合做多行多列的布局;而网格布局grid是二维布局方式更加适合做多行多列布局

缩写

flex-flow其实就是flex-directionflex-wrap 的简写形式

image.png

主轴对齐详解

image.png

  • 默认情况下,弹性布局中的子容器是沿着主轴方向自左向右依次排列的
image.png

那么这三个容器是怎么进行对齐的呢?默认是justify-content: flex-start三个盒子靠在主轴的最左边

  • 同样如果设置成 justify-content: flex-end;那么三个盒子就靠到主轴的最右边
image.png
  • 设置成 justify-content: center;
image.png
  • 设置成 justify-content: space-around;,每个子容器左右2边的空白区域是一样
image.png
  • 设置成 justify-content: space-between;,开始和结束的盒子贴到弹性盒子的边,中间的空白平均分配
image.png

设置成 justify-content: space-evenly;,弹性盒子内部的容器的边距都是一样的

image.png

交叉轴对齐详解

设置交叉轴方向子容器的排列方式和分配空白区域的方式(前提是添加折行属性flex-wrap:wrap;),把全部子容器的整体作为参照物同交叉轴对齐

image.png

注意: align-content属性如果弹性容器的子容器不折行是不生效的,即使没有足够多的子容器折到下一行,但是只要加上折行的属性flex-wrap: wrap;后,align-content就生效了

align-content: flex-end;
flex-wrap: wrap;
image.png

align-content:sretch是它的的默认值,会让子容器根据弹性盒子的高度自动伸缩,只要不给子容器设置高度

image.png

如果给子容器加宽高,设置换行和交叉轴方向子容器在底部

display: flex;
flex-wrap: wrap;
align-content: flex-end;
image.png

设置子容器在交叉轴中间

display: flex;
flex-wrap: wrap;
align-content: center;
image.png

设置子容器在交叉轴方向顶端

  display: flex;
  flex-wrap: wrap;
  align-content: flex-start;
image.png

align-items

image.png

align-items是分别针对每一行容器的对齐方式,而align-content是整体的对齐方式,区别是align-items是不需要加flex-wrap:wrap;就能生效的,而align-content必须加flex-wrap:wrap;才能生效;align-itemsalign-content更常用,因为我们经常要处理的是一行或者一列

下图是,子容器在每一行容器的顶部

align-items: flex-start;
image.png

下图是,子容器在每一行容器的中间

align-items: center;
image.png

如果不给子容器设置高度,并且不设置align-items,那么默认值也是stretch

align-items:baseline; 是根据小写字母x的底部对齐

内联与块的上下左右居中布局

image.png

1.div中的文字居中

display: flex;
align-items: center

2.div中的盒子居中

display: flex;
justify-content: center;
align-items: center

其他方法:

父容器

position: relative;

子容器

position: absolute;
top: 50%;
left: 50%;
transfrom: translate(-50%,-50%);  // 会依据自身的宽度和高度水平方向发生位移

3.默认情况下margin: auto;只会水平方向上的居中,其中的原因是没加BFC;如果我们对父容器加display: flex;那么margin:auto;就会水平和垂直方向都居中,同时之前的margin的传递和合并问题也会得到解决

4.当然也可以使用其他方法使得子元素变成BFC的容器,然后设置margin:auto;

不定项居中布局

类似下图中轮播图中出现的圆形,有几张轮播图是不确定的,如何让他们居中显示?

image.png

display: flex;
justify-content: center;
algin-items: flex-end;

均分列布局

image.png

display: flex;
justify-content: space-between;
alitn-items: flex-end;

子项分组布局

image.png

思路一: 嵌套div使用flex弹性布局

思路二:外层容器使用弹性布局,使用nth-of-type(1)具体指定某个子容器使用margin: auto;margin:auto 的特点就是会沾满整行的空白直到遇到其他容器

flex-grow拓展比例

image.png

  • 如果比例值是1 就占满剩余的所有空间 示例1

  • 当比例值大于等于1的时候,都会沾满整个空间

  • 如果父容器下有2个子div时,子div1是flex-frow:2;子div2是flex-frow:1;它的意思就表示子div1占剩余空间的2/3,子div2占剩余空间的1/3 示例2

  • 如果2个字div的值分别是:div1=>flex-frow:0.2;div2=>flex-frow:0.1;表示如果把剩余空间看成10份,那么div1表示占剩余空间的2/10;div2表示占剩余空间的1/10,剩余的7/10仍然是空白区域 示例3

flex-shrink收缩比例

当子项大于父容器的时候我们该如何处理?(具体的收缩尺寸是要根据自身宽度去计算的)

image.png

  • 如果只有一个子div宽度超过父容器,默认情况下在弹性布局中是不会溢出的,而是自动收缩,收缩的值是1,flex-shrink:1;示例4
  • flex-shrink:0; 表示不自动收缩,按照正常的尺寸进行渲染
  • flex-shrink:0.5; 表示只收缩溢出部分的0.5
  • 如果有2个子容器,他们的尺寸之和超过了父容器,那么在弹性盒子中,子容器会发生收缩以和父容器相同大小,但是子容器并不是按照等比例的收缩,如下图所示,箭头部分就是各自收缩的尺寸。他们实际上是按照各自的宽度去算比例去分配超出部分尺寸去收缩,正如例子中示例5所示,div1的收缩尺寸为超出部分的200px乘以300/300+400=3/7,div2的收缩尺寸为超出部分的200px乘以400/300+400=4/7

image.png

image.png

  • 如果子容器div1是flex-shrink: 2;多出一份占比,另外一div2是flex-shrink: 1;此时,div1就相当于300px * 2 = 600px;div2是400px * 1 = 400px ,就相当于把超出部分算作10份,div1的尺寸是:300 - 6/10 * 200 = 180,div2的尺寸是400 - 4/10*200 = 320 示例6

  • 如果2个子div都是flex-shrink: 0.5; div1的宽度:300-200 * 150/350=214.28,div2的宽度:400-200 * 200/350=285.72

  • 如果div1是flex-shrink: 0.2;div2是flex-shrink: 0.1; div1的宽度:300 - 200 * 3/10 * 60/100=264,div2的宽度:400-200 * 3/10 * 40/100=376 示例7

flex-basis及flex缩写

image.png

flex-basis 设置的尺寸是要优先于宽度(主轴方向在水平方向)或者高度(主轴方向在垂直方向flex-direction: column;)

flex-basis:auto; 那么宽度会自适应内容;flex-basis:0;那么会给容器一个最小宽度,让文字按垂直方向排列; flex-basis:100%; 宽度会和父容器宽度一致


image.png

子容器设置为 flex:1 的含义:

image.png

子容器设置为 flex:0 的含义:

image.png

子容器设置为 flex:auto 的含义:

image.png

子容器设置为 flex:1 0 50% 的含义:

image.png

order 及 align-self

image.png

值越大,优先级越高,越排在后面示例8

相反的也可以给负数,值越小,优先级越低,越排在前面


image.png

algin-self: auto; 的意思是它的对齐方式是跟着父容器的align-items来走的,如果父容器的align-items: center; 那么algin-self: center。如果父容器的align-items: flex-start; 那么algin-self: flex-start 示例9

等高布局

如下图所示,当右侧内容撑起右边的div时,左侧的div的高度也会被自动拉伸和右边的一样高,最外层的高度也会被自动拉伸(弹性布局里的盒子自带自动拉伸的特质) 示例10

image.png

两列与三列布局

image.png

绿色区域为固定宽度,蓝色区域为自适应宽度

两列布局

三列布局

Sticky Footer布局

当页面内容少不满一个屏幕时,footer在可视区最低端;当页面内容足够多,产生滚动条时,footer自动适配到页面最低端(比较适合移动端)

示例11

溢出项布局

image.png

示例12

image.png