Bootstrap

flex布局详解

我正在参加 码上掘金体验活动,详情:show出你的创意代码块

写在前面,由于文章里面有很多flex布局效果图占据了很大的篇幅,导致篇幅很长。以下内容主要分为四个部分:

  1. 常见概念
  2. flex容器相关属性
  3. flex元素相关属性
  4. flex布局的应用
  5. flex布局的兼容性处理

flex布局的相关概念

弹性盒模型

弹性盒模型(Flexible Box模型),也被成为flexbox,是一种一维的布局模型(也就是说一次只能处理一个维度上的元素布局,一行或者一列)。它给flexbox的子元素之间提供了强大的空间分布和对齐能力。

主轴和交叉轴

主轴和交叉轴是两根互相垂直的线。可以用flex-direction设置主轴(设置为row或者column)。那么交叉轴就是垂直于主轴的线。

需要注意的是:一旦设置主轴方向,那么关于flex容器上的盒子的属性都是基于主轴的。

起始线和终止线

起始线和终止线是基于轴线的,主轴和交叉轴都有起始线和终止线。如果flex-direction的方向是row,那么主轴起始线就是左边,终止线就是右边,交叉轴的起始线就是上边,终止线就是下边。如果flex-direction的方向是row-reverse,那么主轴起始线就是右边,终止线就是左边,交叉轴的起始线就是上边,终止线就是下边。如果flex-direction的方向是column,那么主轴起始线就是上边,终止线就是下边。交叉轴起始线就是左边,终止线就是右边。如果flex-direction的方向是column-reverse,那么主轴起始线就是下边,终止线就是上边。交叉轴起始线就是左边,终止线就是右边。

flex容器

采用了flexbox的区域就叫做flex容器。也就是说只要元素的display设置为flex或者inline-flex,那么它就是flex容器。它的所有子元素就是flex元素。

flex元素具有的默认特征:

  • 元素排列为一行(flex-direction的初始值是row)
  • 元素从主轴的起始线开始
  • 元素不会在主轴方向拉伸,但是可以缩小
  • 元素被拉伸来填充交叉轴大小
  • flex-basis属性为auto
  • flex-wrap属性为nowrap

flex布局的属性

flex容器上的属性

1. flex-direction

flex-direction是用来设置主轴的方向,一共可以取四个值:

  • row
  • row-reverse
  • column
  • column-reverse

带有row的表示按行来排列,row-reverse表示倒着排,也就是所从右往左。带有column的表示按列来排列,column-reverse表示从下往上。下面我们一起来看一下具体效果 基础代码如下

<div class="box-wrap">
  <div class="box">我是第1个盒子</div>
  <div class="box">我是第2个盒子</div>
  <div class="box">我是第3个盒子</div>
  <div class="box">我是第4个盒子</div>
  <div class="box">我是第5个盒子</div>
</div>
.box-wrap {
  width: 1100px;
  height: 600px;
  background-color: aquamarine;
  display: flex;
  flex-direction: row;
  .box {
    width: 100px;
    height: 68px;
    background-color: lightcyan;
    border: 1px solid lightgray;
  }
}
复制代码
row
flex-direction: row;
复制代码

效果: image.png

row-reverse
flex-direction: row-reverse;
复制代码

效果: image.png

column
flex-direction: column;
复制代码

效果:

image.png

column-reverse
flex-direction: column-reverse;
复制代码

效果如下:

image.png

2. flex-wrap

flex-wrap属性是用来设置容器内的元素是否换行显示。默认是不会换行的,而且元素会被压缩然后一行显示。可以取以下几种值

  • nowrap:不会换行,默认被压缩,如果不被压缩的话那就超出容器显示
  • wrap: 超出容器时会换行
  • wrap-reverse: 超出容器时会换行,且交叉轴的起始线和终止线会反过来

下面这几种值我们平时不会使用到,仅供了解

  • inherit:指定这个属性应从父元素继承它的值
  • initial:用于设置属性为它的默认值
  • revert: 让当前元素的样式还原成浏览器内置的样式
  • unset: 不做设置。但是与css是否继承属性相关,如果这个属性是可继承属性,那么该设置等同于inherit;如果这个属性是非继承属性,那么该设置等同于initial。

下面我们来看一下常用的三种属性的效果 基础代码如下

<div class="box-wrap">
  <div class="box">我是第1个盒子</div>
  <div class="box">我是第2个盒子</div>
  <div class="box">我是第3个盒子</div>
  <div class="box">我是第4个盒子</div>
  <div class="box">我是第5个盒子</div>
</div>
.box-wrap {
  width: 1100px;
  height: 600px;
  background-color: aquamarine;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  .box {
    width: 300px;
    height: 68px;
    flex-shrink: 0;
    background-color: lightcyan;
    border: 1px solid lightgray;
  }
}
复制代码
nowrap
flex-wrap: nowrap;
复制代码

因为默认是会压缩的,即使你设置了宽度,弹性盒子也会被压缩,所以这里我们为了看到flex元素超出flex容器的效果,将压缩属性设置为0.

效果: image.png

wrap
flex-wrap: wrap;
复制代码

效果如下: image.png

wrap-reverse
flex-wrap: wrap-reverse;
复制代码

效果如下: image.png

3. justify-content

justify-content是用来设置元素在主轴方向上的对齐方式。一共有这几个属性值:

  • center: 居中对齐
  • left: 伸缩元素一个挨一个在对齐容器的左边缘,如果属性的轴(主轴)与内联轴不平行,则left的行为类似于start
  • right: 伸缩元素一个挨一个在对齐容器的右边缘,如果属性的轴(主轴)与内联轴不平行,则right的行为类似于end
  • start: 从主轴的开始排列。每行第一个元素与行首对齐,后面所有元素都与前一个对齐
  • end: 从主轴的行尾排列。每行最后一个元素与行尾对齐,前面所有元素都与后一个对齐
  • flex-start: 从主轴的开始排列。每行第一个弹性元素与行首对齐,后面所有弹性元素都与前一个对齐
  • flex-end: 从主轴的行尾开始排列。每行最后一个弹性元素与行尾对齐,其他元素将与后一个对齐
  • space-around: 弹性元素均匀分布。相邻元素间距离相等,每行第一个元素到行首的距离和每行最后一个元素到行尾的距离等于相邻元素之间距离的一半
  • space-between: 弹性元素均匀分布。相邻元素间距离相等,每行第一个元素到行首的距离和每行最后一个元素到行尾的距离等于0(也就是第一个元素和行首对齐,最后一个元素和行尾对齐)
  • space-evenly: 弹性元素均匀分布。相邻元素间距离相等,每行第一个元素到行首的距离和每行最后一个元素到行尾的距离等于两个元素之间的距离
  • stretch: 可以伸缩
  • baseline: 所有的元素基线对齐
  • first baseline: 指定第一个元素的基线和其他元素对齐
  • last baseline:指定最后一个元素的基线和所有元素对齐
  • safe: 与对齐关键字一起使用,如果选定的关键字会导致元素溢出容器造成数据丢失,那么将会使用 start 代替它。
  • unsafe: 无论项目和对齐容器的相对大小如何,都会遵守给定的对齐值

下面我们来看一下常见的几种属性值的效果 基础代码如下

<div class="box-wrap">
  <div class="box first">我是第1个盒子x</div>
  <div class="box">我是第2个盒子我是第2个盒子我是第2个盒子x</div>
  <div class="box">我是第3个盒子x</div>
  <div class="box">我是第4个盒子x</div>
  <div class="box last">我是第5个盒子x</div>
</div>
.box-wrap {
  width: 1100px;
  height: 600px;
  background-color: aquamarine;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: flex-start;
  .box {
    width: 300px;
    height: 68px;
    font-size: 20px;
    background-color: lightcyan;
    border: 1px solid lightgray;
  }
  .first {
    height: 30px;
    font-size: 12px;
  }
  .last {
    height: 100px;
    font-size: 30px;
  }
}
复制代码
flex-start
justify-content: flex-start;
复制代码

flex-direction的方向是row。效果如下 image.png

flex-direction的方向是column。效果如下 image.png

flex-end
justify-content: flex-end;
复制代码

如果flex-direction的方向是row,效果如下 image.png

如果flex-direction的方向是column, 效果如下:

image.png

center

代码还是和上面的是一样的,只是修改了一下justify-content的属性值

justify-content: center;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下: image.png

space-around
justify-content: space-around;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下: image.png

space-between
justify-content: space-between;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

space-evenly
justify-content: space-evenly;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

stretch
<div class="box-wrap">
  <div class="box">我是第1个盒子x</div>
  <div class="box">我是第2个盒子我是第2个盒子我是第2个盒子x</div>
  <div class="box">我是第3个盒子x</div>
  <div class="box">我是第4个盒子x</div>
  <div class="box">我是第5个盒子x</div>
</div>
.box-wrap {
  width: 1000px;
  height: 300px;
  background-color: aquamarine;
  display: flex;
  flex-direction: column;
  flex-wrap: wrap;
  justify-content: stretch;
  .box {
    width: 300px;
    // height: 68px;
    font-size: 20px;
    background-color: lightcyan;
    border: 1px solid lightgray;
  }
}
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

4. align-items

align-items是用来设置元素在交叉轴上的对齐方式,可以取以下几种值(和justify-content类似):

  • normal:只有在绝对定位的布局中,对于被替代的绝对定位盒子,效果和start一样,其余情况效果和strech的效果一样。
  • flex-start:元素向交叉轴起始线对齐
  • flex-end:元素向交叉轴终止线对齐
  • start:元素向交叉轴起始线对齐
  • end:元素向交叉轴终止线对齐
  • center:元素在交叉轴居中。如果元素在交叉轴上的高度大于容器的高度,那么在两个方向上溢出距离相同
  • left:元素一个挨着一个对齐在对齐容器的左边。如果属性的轴与内联轴不平行,则该值的行为类似于start。
  • right:元素一个挨着一个对齐在对齐容器的右边。如果属性的轴与内联轴不平行,则该值的行为类似于start。
  • self-start:元素向交叉轴起始线对齐
  • self-end:元素向交叉轴终止线对齐
  • baseline、first baseline、last baseline:所有元素向基线对齐。侧轴起点到元素基线距离最大的元素将会于侧轴起点对齐以确定基线。
  • stretch:弹性项包含外边距的交叉轴尺寸被拉升至行高
  • safe:与对齐关键字一起使用。如果选中关键字意味着项溢出对齐容器导致数据丢失,则会将该项对齐,就像对齐模式为启动一样。
  • unsafe:与对齐关键字一起使用。不管项目和对齐容器的相对大小,也不管是否会发生导致数据丢失的溢出,给定的对齐值都会得到尊重。

下面我们来看常见的几个属性的效果 基础代码如下:

<div class="box-wrap">
  <div class="box">我是第1个盒子x</div>
  <div class="box">我是第2个盒子我是第2个盒子我是第2个盒子x</div>
  <div class="box">我是第3个盒子x</div>
  <div class="box">我是第4个盒子x</div>
  <div class="box">我是第5个盒子x</div>
</div>
.box-wrap {
  width: 1000px;
  height: 300px;
  background-color: aquamarine;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: flex-start;
  .box {
    width: 300px;
    font-size: 20px;
    background-color: lightcyan;
    border: 1px solid lightgray;
  }
}
复制代码
flex-start
align-items: flex-start;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

flex-end
align-items: flex-end;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

center
align-items: center;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

stretch
align-items: stretch;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

特别说明

最后说一下flex-start,start和left(同理flex-end, right和end)的区别

flex-start,start和left都是表示左对齐,只是flex-start是和设置的flex-direction属性有关,而start是和元素的writing-mode属性(书写模式,比如中文是从左往右固定的)有关。left时若flex-direction属性不适用,那具体表现等同start。

safe和unsafe的作用? safe属性是确保你无法将那些本身就渲染出屏幕外的且浏览器content没办法到达进行处理

5. align-content

align-content属性是设置浏览器如何沿着弹性盒子布局的交叉轴在内容项和周围分配空间。可以取以下几种值:

  • start: 所有行从容器的起始边缘开始填充
  • end: 所有行从容器的结束边缘开始填充
  • flex-start: 所有行从垂直轴起点开始填充。第一行的垂直轴起点边和容器的垂直轴起点边对齐。接下来的每一行紧跟前一行
  • flex-end: 所有行从垂直轴末尾开始填充。最后一行的垂直轴起点边和容器的垂直轴起点边对齐。所有后续行与前一个对齐
  • center: 所有行朝向容器的中心填充。每行互相紧挨,相对于容器居中对齐。容器的垂直轴起点边和第一行的距离相等于容器的垂直轴终点边和最后一行的距离。
  • normal: 这些项按默认位置填充,就像没有设置对齐内容值一样。
  • baseline first baseline last baseline: 指定参与第一个或最后一个基线对齐:将盒子的第一个或最后一个基线集合的对齐基线与它的基线共享组中所有盒子的第一个或最后一个基线集合中的相应基线对齐。第一个基线的回退对齐是start,最后一个基线的回退对齐是end。
  • space-between: 所有行在容器中平均分布。相邻两行间距相等。容器的垂直轴起点边和终点边分别与第一行和最后一行的边对齐。
  • space-around: 所有行在容器中平均分布,相邻两行间距相等。容器的垂直轴起点边和终点边分别与第一行和最后一行的距离是相邻两行间距的一半。
  • space-evenly: 所有行沿垂直轴均匀分布在对齐容器内。每对相邻的项之间的间距,主开始边和第一项,以及主结束边和最后一项,都是完全相同的。
  • stretch: 拉伸所有行来填满剩余空间。剩余空间平均地分配给每一行。
  • safe: 与对齐关键字一起使用。如果所选的关键字意味着项溢出对齐容器(data loss),则将采用备用策略对项进行对齐,就像启动了 start 对齐模式一样。
  • unsafe: 与对齐关键字一起使用。无论元素和对齐容器的相对大小如何、是否会导致一些元素溢出可见范围(data loss),都使用给定的对齐值。

下面我们来看几种常见的效果

flex-start
align-content: flex-start;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

flex-end
align-content: flex-end;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

center
align-content: center;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

baseline
align-content: baseline;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下:

image.png

stretch
align-content: stretch;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下: image.png

space-between
align-content: space-between;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下: image.png

space-around
align-content: space-around;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下: image.png

space-evenly
align-content: space-evenly;
复制代码

如果flex-direction的方向是row,效果如下: image.png

如果flex-direction的方向是column,效果如下: image.png

特别说明

??? align-items和align-content的区别

  • align-items和align-content这两个属性都是作用在交叉轴上的。只是align-items设置的是flex元素的对齐方式,而align-content设置的是flex元素和交叉轴上的空白区域的对齐方式。
  • align-items只管flex元素的对齐方式,如果出现换行,那么每行元素之间的距离都是平均分配的。而align-content属性就是用来设置flex元素和空白区域之间的分配。
  • align-items只有flex相关的属性值(比如: flex-end, flex-start, center, stretch),align-content除了这些属性值之外,还具有space相关属性(比如:space-between,space-around,space-evenly)
6. 简写属性flex-flow

flex-flow是flex-direction和flex-wrap的简写形式。具体语法如下:

flex-flow = <'flex-direction'>  || <'flex-wrap'>  
复制代码

默认值是: flex-flow: row nowrap;

flex元素上的属性

1. flex-grow

flex-grow是用来设置flex元素在主轴方向上的尺寸的增长系数,规定了flex-grow项在flex容器中分配剩余空间的相对比例。 具体计算方式如下: 某个元素的增长比例 = 当前项的flex-grow的值 / 所有项的flex-grow的值的和 它的取值主要是数值,初始值是0

示例:

<div class="box-wrap">
  <div class="box first">我是第1个盒子x</div>
  <div class="box">我是第2个盒子x</div>
  <div class="box">我是第3个盒子x</div>
  <div class="box">我是第4个盒子x</div>
  <div class="box">我是第5个盒子x</div>
</div>
.box-wrap {
  width: 1000px;
  height: 300px;
  background-color: aquamarine;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  .box {
    width: 100px;
    font-size: 20px;
    background-color: lightcyan;
    border: 1px solid lightgray;
    flex-grow: 1;
  }
  .first {
    flex-grow: 2;
  }
}
复制代码

效果如下: image.png

特别说明

flex-grow是针对每行如果有多余的空间会按照这个设置的值来进行增长。因此对于设置可以换行(flex-wrap: wrap)的情况,如果最后一行的元素按照原来的宽度不能填充整行空间,那么这一行设置了flex-grow属性的元素就会填充剩余空间。

.box-wrap {
  width: 1000px;
  height: 300px;
  background-color: aquamarine;
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  .box {
    width: 300px;
    font-size: 20px;
    background-color: lightcyan;
    border: 1px solid lightgray;
    flex-grow: 1;
  }
  .first {
    flex-grow: 2;
  }
}
复制代码

效果如下: image.png

2. flex-shrink

flex-shrink和flex-grow相反,表示的是收缩比例。是用来设置flex元素在主轴方向上的尺寸的收缩系数,规定了flex-shrink项在flex容器中被收缩的相对比例。 具体计算方式如下: 某个元素的增长比例 = 当前项的flex-shrink / 所有项的flex-shrink的值的总和 它的取值主要是数值,初始值是1

示例:

<div class="box-wrap">
  <div class="box first">我是第1个盒子x</div>
  <div class="box">我是第2个盒子x</div>
  <div class="box">我是第3个盒子x</div>
  <div class="box">我是第4个盒子x</div>
  <div class="box">我是第5个盒子x</div>
</div>
.box-wrap {
  width: 1000px;
  height: 300px;
  background-color: aquamarine;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  .box {
    width: 300px;
    font-size: 20px;
    background-color: lightcyan;
    border: 1px solid lightgray;
  }
  .first {
    flex-shrink: 2;
  }
}
复制代码

效果如下: image.png

特别说明
  1. flex-shrink只有在不换行(flex-wrap: nowrap)的情况下才会生效, 因为如果一行放不下换行的方式就不会涉及到剩余空间压缩了。
  2. flex-shrink可以和flex-grow同时使用,因为它们的使用场景是相反的,只会在特定场景下生效,不会冲突。
3. flex-basis

flex-basis是用来设置flex元素在主轴方向上的初始大小。如果不使用box-sizing改变盒模型的话,那么这个属性就决定了flex元素的内容盒(content-box)的尺寸。 属性值和设置宽高的属性值一样。如下:

  • width值: 可以是数值+单位,也可以是百分比
  • content: 基于flex元素的内容自动调整大小
特别说明
  1. flex-basis和width的区别:当一个元素同时设置了flex-basis(值为auto除外)和width(方向为column时设置了height), flex-basis优先级更高。但是如何设置了min-width或者max-width。那么它们会同时控制flex-basis。

    • flex-basis:100px; min-width: 50px; 最终宽度就是100px;
    • flex-basis:100px; max-width: 50px; 最终宽度就是50px;
  2. 怎样设置flex item的基本大小?

    • 如果设置了flex-basis为auto或者content, 那么flex item的基本大小就是内容的大小。
    • 如果设置了flex-basis为0, 那么flex item的基本大小不在空间分配计算的考虑之类。
    • 如果设置了flex-basis为不为0的长度单位, 那么flex item的基本大小就是这个设置的长度单位。
4. align-self

align-self会对齐当前grid或flex行中的元素,并覆盖已有的align-items的值。也就是说,align-self设置的仅仅是当前元素在当前行中的对齐方式。取值有以下几种情况;

  • auto: 设置为父元素的align-items的值
  • normal: 只有在绝对定位的布局中,对于被替代的绝对定位盒子,效果和start一样,其余情况效果和strech的效果一样。
  • flex-start:元素向交叉轴起始线对齐
  • flex-end:元素向交叉轴终止线对齐
  • self-start:元素向交叉轴起始线对齐
  • self-end:元素向交叉轴终止线对齐
  • center:元素在交叉轴居中。如果元素在交叉轴上的高度大于容器的高度,那么在两个方向上溢出距离相同
  • baseline、first baseline、last baseline:所有元素向基线对齐。侧轴起点到元素基线距离最大的元素将会于侧轴起点对齐以确定基线。
  • stretch:弹性项包含外边距的交叉轴尺寸被拉升至行高
  • safe:与对齐关键字一起使用。如果选中关键字意味着项溢出对齐容器导致数据丢失,则会将该项对齐,就像对齐模式为启动一样。
  • unsafe:与对齐关键字一起使用。不管项目和对齐容器的相对大小,也不管是否会发生导致数据丢失的溢出,给定的对齐值都会得到尊重。

下面我们来看一下常用的几种属性的效果:

flex-start
align-self: flex-start;
复制代码

效果如下:

image.png

flex-end
align-self: flex-end;
复制代码

效果如下: image.png

center
align-self: center;
复制代码

效果如下: image.png

baseline
align-self: baseline;
复制代码

效果如下: image.png

stretch
align-self: stretch;
复制代码

效果如下:

image.png

5. order属性

order属性是用来设置单个flex元素在视觉顺序中的显示位置。属性值为自然数,默认值为0. 数值越大,越往后排列。 image.png

示例

只给第一个元素添加order属性,那么其他元素的order默认都是0

.first {
  flex-basis: 100px;
  max-width: 50px;
  flex-grow: 0;
  order: 5;
}
复制代码

效果如下:

image.png image.png

6. 简写属性flex

flex属性是flex-grow, flex-shrink, flex-basis的简写,具体语法如下:

flex = none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]  
复制代码

初始值:flex-grow: 0, flex-shrink: 1, flex-basis: auto

单值语法:
  • 一个无单位数 (): 它会被当作flex: 1 0; 的值被假定为 1,然后 的值被假定为0。
  • 一个有效的**宽度 (width)**值:它会被当作 的值。
  • 关键字none,auto或initial.
双值语法:

第一个值必须为一个无单位数,并且它会被当作 的值。第二个值必须为以下之一:

  • 一个无单位数:它会被当作 的值。
  • 一个有效的宽度值:它会被当作 的值。
三值语法:
  • 第一个值必须为一个无单位数,并且它会被当作 的值。
  • 第二个值必须为一个无单位数,并且它会被当作 的值。
  • 第三个值必须为一个有效的宽度值,并且它会被当作 的值。

flex布局的应用

导航

导航栏的布局在我们前端的页面的布局中很常见,一般主要是以下这种: image.png image.png image.png

这些效果都是可以通过flex布局来实现的。

示例
<ulclass="box-wrap">
  <li class="item">首页</li>
  <li class="item">海外直购</li>
  <li class="item">考拉自有品牌</li>
  <li class="item">品质奶粉</li>
  <li class="item">人气面膜</li>
  <li class="item">充值</li>
</ul>
.box-wrap {
  height: 40px;
  padding: 10px 0px;
  border-bottom: 1px solid lightgray;
  display: flex;
  justify-content: space-evenly;
}
复制代码

效果如下: image.png

拆分导航

拆分导航布局指的是一部分导航在左边,一部分导航在右边,类似于上面考拉的导航。有两种实现方式

  1. 对于导航元素之前的距离,我们一般可以通过设置间距来控制元素之间的距离,将某些相等的间距设置成固定的值,中间不确定的间距很大的元素设置成auto
<ulclass="box-wrap">
  <li class="item first">考拉欢迎你!</li>
  <li class="item">登录</li>
  <li class="item">免费注册</li>
  <li class="item">手机考拉</li>
  <li class="item mar_item">每日签到</li>
  <li class="item">我的订单</li>
  <li class="item">个人中心</li>
  <li class="item">客户服务</li>
  <li class="item">充值中心</li>
  <li class="item">消费者权益</li>
  <li class="item">更多</li>
  <li class="item">视频内容</li>
</ul>
.box-wrap {
  height: 40px;
  padding: 10px 0px;
  background-color: #000;
  color: #999;
  display: flex;
  .item {
    margin-right: 22px;
  }
  .mar_item {
    margin-left: auto;
  }
  .first {
    margin-left: 22px;
  }
}
复制代码

效果如下: image.png

  1. 将左边的元素用用一个容器包裹,将右边的元素用一个容器包裹,这样就可以把这两个容器元素看成是两个flex元素,给他们的容器设置justify-content: space-between即可。
<divclass="box-wrap">
  <ul class="item_wrap">
    <li class="item">考拉欢迎你!</li>
    <li class="item">登录</li>
    <li class="item">免费注册</li>
    <li class="item">手机考拉</li>
  </ul>
  <ul class="item_wrap">
    <li class="item">每日签到</li>
    <li class="item">我的订单</li>
    <li class="item">个人中心</li>
    <li class="item">客户服务</li>
    <li class="item">充值中心</li>
    <li class="item">消费者权益</li>
    <li class="item">更多</li>
    <li class="item">视频内容</li>
  </ul>
</div>
.box-wrap {
  height: 40px;
  padding: 10px 0px 10px 22px;
  background-color: #000;
  color: #999;
  display: flex;
  justify-content: space-between;
  .item_wrap {
    display: flex;
    .item {
      margin-right: 22px;
    }
  }
}
复制代码

效果如下: image.png

元素居中

有了flex布局,那么设置元素的水平居中,垂直居中就变得非常简单了。这里我就不贴效果图了

.box {
  display: flex;
  align-items: center;
  justify-content: center;
}
复制代码

绝对底部

绝对底部的布局在开发中也是比较常见的尤其是在移动端更是非常常见,在出现flex布局之前,实现这类布局效果我们都是用定位来实现的(绝对定位或者固定定位),但是使用这些方式有一些很明显的弊端:

  1. 使用绝对定位的时候去找它的包含块设置相对定位是一个很麻烦的过程。
  2. 这两个定位都是脱离文档流,也就是说如果不给页面底部留一段空白,很容易造成绝对底部的内容遮挡页面底部的内容。

其实这类布局也可以使用flex布局来实现,这样就能避免这些问题的发生。但是这种方式有一个问题,flex的容器必须有一个高度,否则容器的高度是根据内容来的,就不能达到位于底部了。所以这类布局只适合高度固定的页面布局中。而且针对那种固定在页面底部的布局也不适用。 总而言之:这类flex也不能完全替代上面介绍的绝对底部的页面布局,在实际项目需求中还是要根据场景去选则布局方式。

示例

<div class="page_wrap">
  <div class="content_wrap">这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。</div>
  <footer>网页底部</footer>
</div>
.page_wrap {
  display: flex;
  flex-flow: column nowrap;
  height: 200px;
  .content_wrap {
    flex: 1 1 auto;
  }
}
复制代码

效果如下:

image.png

媒体对象

媒体对象表示的是一种一侧是图片或者其他元素并且另一侧是描述性文字的两列盒子,一般常见的就是推文,评论这种。而且媒体对象理想状态下是可以翻转的。

这种布局就很适合使用flex布局了。

<div class="page_wrap">
  <div class="img_wrap"><img src="../assets/logo.png" alt=""></div>
  <div class="desc_wrap">这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。这是一段说长不长,说短不短的内容。</div>
</div>
.page_wrap {
  display: flex;
  align-items: flex-start;
  .img_wrap {
    width: 300px;
    height: 300px;
  }
  .desc_wrap {
    flex: 1 1 auto;
  }
}
复制代码

效果如下:

image.png

表单控制按钮

几乎大部分的网站都有个输入搜索的功能,以京东为例。像这种如果使用普通布局是有点麻烦的,一般都用到了定位布局,而且在设置垂直居中对齐上需要很细致地去调整。但是如果使用到flex布局那么就会比较简单。

示例
<divclass="search_wrap">
  <input type="text" name="" id="searchVal" class="text_input"/>
  <button>搜索</button>
</div>
.search_wrap {
  display: flex;
  .text_input {
    flex: 1 1 auto;
  }
}
复制代码

效果如下:

image.png

多列布局

多列布局是我们布局方式中非常常见的一种布局方式。可以细分为单列布局,两列布局,三列布局,多列布局。这里我们主要介绍一下多列等宽布局。其他布局详见我另一篇文章:常见布局的实现

示例
<div class="item_wrap">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
</div>
.item_wrap {
  display: flex;
  width: 1000px;
  flex-wrap: wrap;
  justify-content: space-around;
  .item {
    width: 220px;
    height: 100px;
    margin-top: 10px;
    background-color: aquamarine;
    flex: 0 0 auto;
  }
}
复制代码

这时候如果是8个元素,每行显示4个元素,效果如下:

image.png

最后一行元素达不到每行的元素数,不能和上面的元素一样对齐

但是如果只有7个元素,或者总元素个数不是4的倍数,那么最后一行显示就会乱。

image.png 解决方式: 在最后一行增加空元素(span, i, div元素都可以),空元素个数为列数 - 2

<divclass="item_wrap">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <i class="blank_item"></i>
  <i class="blank_item"></i>
</div>
.blank_item {
  width: 220px;
}
复制代码

效果如下:

image.png

flex布局的兼容性处理

虽然flex布局对于现在主流浏览器都是可以兼容的(一些新的flex属性除外),只有IE6-9,Opera10-11.5不兼容。但是在日常项目中,我觉得你完全可以使用flex布局,除非你需要兼容低版本的浏览器,那么如何解决flex布局的兼容性问题呢?下面提供了几种方式;
复制代码

1. IE10和UC浏览器需要加前缀

建议都加上浏览器前缀

{display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
}
复制代码

对于webpack项目中,可以使用插件自动给我们加上前缀。

2. 使用浮动代替flex布局

在flex布局出现之前,我们实现这些布局主要用到的就是浮动,因此对于不支持flex布局的浏览器,我们可以使用float浮动布局覆盖flex布局。

来源:https://juejin.cn/post/7142033884434628644
;