Flex布局

170 阅读9分钟

写在前面

今天和同事聊到flex布局,发现一个很有意思的现象,就是当flex-basis和width同时存在的话,盒子的宽度是怎么表现的。因为自己没去尝试过嘛,所有就想当然的说了一下,俩种可能嘛,第一种就是直接根据flex-basis设置的宽度来显示,第二种就是谁在后面显示谁的宽度吧。我心想你问这种问题总不能是在都存在的情况下,显示width的宽度吧?哈哈哈,果然还是我太年轻了。哎,学到了就记录一下吧。个人感觉还蛮有意思的。

今天要学习的内容有以下几点

  1. 什么是flex布局
  2. flex布局的基础配置
  3. flex布局怎么实现水平垂直居中
  4. flex-basis和width同时存在盒子宽度怎么显示

页面布局,常用的有标准流,浮动(float),定位(position),变换(transform),flex(弹性盒布局),grid(网格布局)。这全是知识点,不过前面几种比较简单,基本上看过俩遍就会了,这里就不做介绍了,grid网格布局,功能也非常的强大,不过好像兼容性问题比较严重,我在项目上也很少用(这里打个//todo)等我有时间详细的去学习一下,未来肯定也是主流布局方式。今天的主角儿是flex。

什么是flex

flex布局又被称之为弹性盒布局,主要是由于它可以伸缩的特性进行形象化的描述,所以称之为弹性盒布局

采用flex布局的元素,属性设置为display:flex,该元素被称为flex容器,容器内所有子元素被称之为flex项目,容器会生成俩条轴,默认沿水平方向的为主轴,竖直方向的为侧轴。主轴和侧轴非常重要,它决定了元素的排列方向。

基础配置

先写一下基础的结构

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Flex</title>
</head>
<style>
  .fa{
    width: 200px;
    height: 200px;
    background-color: pink;
  }
  .son{
    height: 30px;
    width: 30px;
  }
  .son1{
    background-color: hotpink;
  }
  .son2{
    background-color: deeppink;
  }
  .son3{
    background-color: plum;
  }
</style>
<body>
  <div class="fa">
    <div class="son son1">1</div>
    <div class="son son2">2</div>
    <div class="son son3">3</div>
  </div>
</body>
</html>

页面是这样的

image.png

然后先说一下容器属性

  1. display:flex ——设置布局格式为flex布局(当为flex的时候,flex布局的默认属性就已经生效了),页面就会属性配置的默认值进行展示。页面就会变成这样。

image.png

  1. flex-direction ——设置主轴方向,默认的主轴方向是从左到右(row)
  • row(默认值):主轴为水平方向,从左到右
  • row-reverse:主轴为水平方向,从右到左
  • column:主轴为垂直方向,从上到下
  • column-reverse:主轴为垂直方向,从下到上 按属性来四张图,看一下这个主轴到底什么效果,当然row我们已经看过了,主要看剩下的三种。效果很明显,从左到右,从右到左,从上到下,从下到上。

image.png image.png image.png

  1. flex-wrap ——设置项目是否换行
  • nowrap(默认值):不换行
  • wrap:换行
  • wrap-reverse: 从下往上换行,我迷了,不知道该怎么解释这个属性 在这里要看是否换行的话,肯定项目要多,我这个三个项目即使设置了换行,也没有效果,所有这里将项目数量怎加到10个吧

很明显盒子本来是30px宽,现在被压缩成了20px,并且不会换行,也不会超出父元素 image.png

换行了,但是换行的同时,中间有很大的空隙,应该也是某个默认属性导致的

image.png

我自己都看不懂了,我还以为是按S形进行换行呢,又草率了

image.png

  1. justify-content —— 在主轴方向上的对其方式
  • flex-start(默认值):项目在主轴方向上左对齐
  • flex-end: 项目在主轴方向上右对齐
  • center: 居中
  • space-between: 俩端对其,项目之间的间隔都相等
  • space-around: 每个项目的俩侧间隔相等 现在不需要那么多项目了,我们还是回到3个项目来看效果,默认值就不看了,就是上面图2的效果

这个图和上面flex-direction: row-reverse;好像啊,但是仔细一看,一个是321,一个是123。区别就在这里,flex-direction: row-reverse;表示的是从右到左的概念,而justify-content: flex-end;表示靠着右边。注意区分。

image.png

image.png

image.png

image.png

  1. align-items:项目在侧轴上的对其方式,下面是侧轴为从上到下的情况
  • flex-start(默认值): 表现为贴着上边
  • flex-end:表现为贴着下边
  • center:表现为居中(实现水平垂直居中的重点)
  • baseline: 文字基线对齐
  • stretch:拉伸(当未设置高度或高度为auto时,项目自动撑满容器高度)

前面几个都差不多,主要看一下baseline和stretch的效果吧 好像没什么效果啊,说的跟文字基线对其,那把文字大小改一下试试。

image.png image.png image.png

  1. align-content:主轴方向发生换行的情况下生效,表示有俩行主轴才生效。
  • flex-start(默认值): 表现为贴着上边
  • flex-end:表现为贴着下边
  • center:表现为居中(实现水平垂直居中的重点)
  • space-between: 轴线之间平分间距
  • space-around: 每根轴线俩侧的间隔都相等
  • stretch:拉伸(当未设置高度或高度为auto时,项目自动撑满容器高度) 这个就不截图了,自己试试吧

说一下项目的属性

  1. order:定义项目的排列顺序,数值越小,排列越靠前,默认是0
  2. flex-grow:定义项目的放大比例,默认为0,有剩余空间也不放大
  3. flex-shrink:定义项目的缩小比例,默认为1,如果空间不足,该项目将缩小,也就就是我们看到当有10个项目且不换行的效果。
  4. flex-basis:定义项目宽度的基准值。
  5. align-self: 定义单个项目与其他项目不一样的对其方式,可覆盖容器中的align-items属性
  6. flex: 属性是flex-grow,flex-shrink,flex-basis三个属性的缩写方式

简单看一下order的效果吧,给2这个项目设置order为-1。其他俩个是默认值为0

image.png

设置1的扩张比为1, 2的扩张比为2,3的扩张比为3,看下效果。可以看出来剩余的空间被分成了6份,1占了一份,2占了2份,3占了三份。那么压缩比大概也是相同的道理,数值越大,被压缩的越多,就不截图了

image.png

这是父元素给了align-items为center,然后2元素给了align-self为flex-end的效果

image.png

实现水平垂直居中

根据上面所学的基础属性,应该很多人都知道怎么实现水平垂直居中了吧。对,就是你想的那样,很简单,直接上代码

image.png

直接给父元素设置这俩个属性,就可以实现所有子元素的垂直居中了。是不是超简洁。但是还有另外一种方式,也只要俩行代码就可以实现。但是只能有一个项目的时候可以使用。就是在容器上给display:flex,在son上给margin:auto

.fa{
    width: 200px;
    height: 200px;
    display: flex;
    background-color: pink;
  }
  .son{
    height: 30px;
    width: 30px;
    margin: auto;
  }

image.png

flex-basis和width同时存在

终于写到篇的重点了,在写它俩同时存在之前,先单独分析一下。

  1. 首先只有width的情况
  • 当值不超过盒子的宽度时
  • 当值超过盒子的宽度时 俩种情况下,盒子的宽度都是30px

image.png image.png

  1. 只要flex-basis的情况
  • 当值不超过盒子的宽度时
  • 当值超过盒子的宽度时

image.png image.png

表现不太一样,flex-basis会将盒子撑大,真正的实现了弹性盒

  1. 再看width和flex-basis都存在的情况下
  • 没有值的情况,width设置30px,flex-basis:60px,(测试俩次,一次width在前,一次flex-basis在前,效果是一样的)
  • 当俩个都存在且值不超过盒子的宽度
  • 当俩个都存在且值超过盒子的宽度

image.png

image.png

image.png

迷不迷?哈哈哈,意料之外吧? 当都存在的时候总结一下:

  1. 宽度按flex-basis设置的宽度展示
  2. 但是当内容超出的时候,伸缩特性也消失了

你以为到这就为止了吗?哈哈哈,那你也太浅了,我又把width和flex-basis的值换了一下,因为我觉得有可能是按照宽度较宽的来显示的。所以我设置了width的宽度为60px,width的宽度为30px

  • 没有值的情况
  • 有值没超过宽度的情况
  • 有值超过宽度的情况

image.png

image.png

image.png

嗯?迷不迷?测完俩个我都准备收工了,第三个宽度变宽了。对照前面三种,加刚测试的三种情况,总结如下:

  1. 当没有值,或值不超过width和flex-basis最小值的情况,按照flex-basis的宽度显示
  2. 当值超过width和flex-basis最大值的时候,按照最大值显示宽度

总算完结可以撒花了,哈哈哈,你又错了,还是太浅了,我又想了一下,假如值在最小值和最大值之间又会怎么显示呢?话不多说,再接着测吧,已经5月20日00:01分了,这个点情侣们应该都在收红包吧?老实人,继续搞研究,不废话了,下面的情况一起列出来,给测试结果

当width为20px,flex-basis:为100px

  • 值 < 20px
  • 20px < 值 < 100px
  • 100px < 值 image.png

image.png

image.png

当width为100px,flex-basis:为20px

  • 值 < 20px
  • 20px < 值 < 100px
  • 100px < 值

image.png

image.png

image.png

终极总结:

  1. 当俩者都存在,并且没有内容的时候,按flex-basis设置的宽度显示
  2. 当俩个都存在,并且width较小时,按flex-basis显示宽度,弹性效果失效,宽度不会随内容长短进行改变
  3. 当俩个都存在,并且flex-basis较小时,没有内容时或内容小于最小值时,按照最小值显示,当内容大于最小值,小于最大值时,宽度随着内容的增加而变宽,当内容大于最大值的时候,宽度为最大值,弹性效果失效。

写在最后

不写了,累死了,从6点,码到12点半,这篇3300多字,加好多图,多看几遍,应该能记住吧。自己也没想到能写这么多。应该没有其他情况了吧。不说了,看完的读者,你也很厉害,祝你520快乐。没有对象的跟代码过吧。但是也要快乐哈。