display: flex一些细节

1,731 阅读4分钟

默认值

默认值 名称
容器 flex-direction row 项目将一个个水平显示,正如一个行一样。
flex-wrap nowrap 项目不拆行或不拆列,一行显示所有项目或一列显示所有项目。
flex-flow row nowrap flex-flow 是 flex-direction flex-wrap 的简写。
justify-content flex-start 项目居(靠)左显示
align-items stretch 如果项目未设置高度,或设为 auto,将占满整个容器高度。
align-content stretch 轴线占满整个交叉轴
项目 align-self auto 表示继承父元素 align-items 属性,如果没有父元素(容器),则等同于 stretch
flex-grow 0 项目不拉伸,即使父元素(容器)没有被占满。
flex-shrink 1 如果容器空间不足,该项目将缩小。
flex-basis auto 项目本身的大小
flex 0 1 auto flex 是 flex-grow flex-shrink flex-basis 的简写
order 0 定义项目的排列顺序

一些细节:

(1)align-items: stretch;

当 flex-direction: row; 水平按行排列时,项目没有设置高度,或者高度为 auto 时,align-items: stretch; 会拉伸项目,高度占满容器。

当 flex-direction: column; 按列排列时,项目没有设置宽度,或者宽度为 auto 时,align-items: stretch; 会拉伸项目,宽度占满容器。

(2)flex-basis 和宽度的优先级关系如下:

min-width/max-width > flex-basis > width

.item:nth-child(1){
  flex-basis: 50px;
}
.item:nth-child(2){
  flex-basis: 50px;
  min-width: 100px;
}
.item:nth-child(3){
  flex-basis: 150px;
  max-width: 100px;
}
.item{
  width: 200px;
  height: 100px;
}

flex-basis 设置宽度的优先级肯定是高于 width,即使 width 设置在 flex-basis 之后。

当 flex-basis 比 min-width 小的时候,项目表现 min-width 的值;否则表现 flex-basis 的值。

当 flex-basis 比 max-width 大的时候,项目表现为 max-width 的值,否则表现为 flex-basis 的值。

flex: 1

面试常问问题,flex:1 表示什么?我们来看下 Chrome 浏览器给出的答案:

flex: 1 1 0; 又是什么呢?

可以看到浏览器会给 flex-basis 加上单位 % 和 px。

对 flex 属性简写值整理如下:

简写等同于备注
flex: 3flex: 3 1 0%
flex: 1flex: 1 1 0%
flex: 0flex: 0 1 0%
flex: noneflex: 0 0 auto
flex: autoflex: 1 1 auto

flex: 1; 等同于 flex: 1 1 0%;含义是项目在容器有多余空间的时候会拉伸、项目在容器没有空间的时候会缩小、项目本身尽量占较小的空间显示。

flex: 0; 等同于 flex: 0 1 0%; 含义是即使容器有多余空间项目不会拉伸、项目在容器没有空间的时候会缩小、项目本身尽量占较小的空间显示。所以“普通人类”文本换行显示,尽量占较小的空间。

flex: none; 等同于 flex: 0 0 auto; 含义是即使容器有多余空间项目不会拉伸、即使容器没有空间也不会缩小、项目本身 auto 显示。

flex: auto; 等同于 flex: 1 1 auto; 含义是容器有多余空间的时候会拉伸、项目在容器没有空间的时候会缩小、项目本身 auto 显示。

总结:项目本身的宽度以及是否拉伸或者缩小,跟 flex-grow flex-shrink flex-basis width max-width min-width 都是有关的,不能单单根据其中的一项或者两项去计算,而要根据flex-grow flex-shrink flex-basis width max-width min-width 一起计算。整体而言,flex-grow 控制容器有多余空间项目是否会拉伸;flex-shrink 控制容器空间不够项目是否会缩小;而 flex-basis 控制项目本身的宽度,浏览器根据这个属性,计算主轴是否有多余空间,flex-basis: 0; 项目会尽量占较小空间显示。flex-basis: auto; 本身大小显示。

实际应用

栅格布局

误区:以为 flex:1;flex:2; 可以按 1:2 比例分配项目;其实不然,flex: n 只是在确定有多余空间的时候才按照相应的比例分配,而不是项目本身的比例,项目本身的比例是通过 max-width 实现的。

根据 flex + max-width 实现等比例栅格布局如下:

    .item{
      height: 100px;
      flex:0 0 33.33333333%;  
      max-width: 33.33333333%;
    }

antdv 实现栅格布局的方式正是如此:

当然可以只使用 width + max-width 实现栅格布局,但是那样对于子元素的对齐控制就没有 flex 那样灵活了。

flex: none

antd 顶部导航:

image.png

image.png

flex: auto

张鑫旭大佬提到的 flex: auto 可以用在导航菜单中,各导航菜单占的大小会按照内容的大小分配,如下:

<nav class="flex">
  <span>首页</span>
  <span>排行榜</span>
  <span>我的订单</span>
  <span>个人中心</span>
</nav>
nav span {
    flex: auto;
    line-height: 3rem;
    background: #444;
    color: #fff;
    text-align:center;
}
span + span {
    border-left: 1px solid #eee;
}

image.png

flex:0 flex:1 flex:none flex:auto应该在什么场景下使用?
你应该知道的 flex 布局

本文正在参加「金石计划」