关于flex布局我们应该熟悉的

前言

CSS3最喜欢的新属性之一便是flex布局属性,用六个字概括便是简单、方便、快速

Flex 是 Flexible Box 的缩写,意为"弹性布局"

简单来说,就是通过给元素盒子设置一些属性,让元素盒子具有伸缩性

有别于之前的display+position+float布局,flex布局可以简便、完整、响应式地实现各种页面布局

设为 Flex 布局以后,子元素的float、clear和vertical-align属性将失效

概念

首先我们来看下下面这张图,这张图我相信了解过flex布局的人都应该见过

image

采用flex布局的弹性盒子,称为flex容器(flex container),简称“容器”

盒子里边的子元素称flex项目(flex item),简称“项目”

上图中我们还能看到容器默认存在两根轴:

水平的主轴(main axis)

垂直的交叉轴(cross axis)

主轴和交叉轴的位置是可以变换的,依赖于flex-direction,默认方向是row

属性

flex属性主要基于两块,一块是使用flex布局的盒子容器,另一块是其子元素

基于盒子容器

  • flex-direction : 主轴方向(子项目的排列方向)
  • flex-wrap : 换行 默认nowrap
  • flex-flow : flex-direction属性和flex-wrap属性的简写 默认row nowrap
  • justify-content : 项目在主轴上的对齐方向
  • align-items : 项目在交叉轴上如何对齐
  • align-content : 多根轴线的对齐方式

基于子元素项目

  • order : 项目的排列顺序
  • flex-grow : 项目的放大比例
  • flex-shrink : 项目的缩小比例
  • flex-basis : 项目占据的主轴空间
  • flex : flex-grow, flex-shrink 和 flex-basis的简写
  • align-self : 单个项目的对齐方式

接下来的内容主要是针对在项目中使用频率比较高的属性

flex-direction 主轴方向(子项目的排列方向)

默认值是row水平方向,起点在左

与之相反的就是column垂直方向,起点在上

还有两个属性值为row-reversecolumn-reverse,与row和column的区别就在于在于起点相反

有点类似于行内元素不换行与块级元素的换行

justify-content 项目在主轴上的对齐方向

justify-content 是一个非常重要的属性,它的5个属性值都是我们在项目中经常用到的,分别是:

  • flex-start(默认值):左对齐

  • flex-end:右对齐

  • center: 居中

  • space-between:两端对齐,项目之间的间隔都相等

  • space-around:每个项目两侧的间隔相等

align-items 项目在交叉轴上如何对齐

同justify-content一样,也是非常重要的属性,同样也有5个属性值,分别是:

  • flex-start:交叉轴的起点对齐

  • flex-end:交叉轴的终点对齐

  • center:交叉轴的中点对齐

  • baseline: 项目的第一行文字的基线对齐

  • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度

demo

针对于上面的两种属性,写了个简单的demo,我们可以看下效果,也方便添加后面属性的对比

html
<div class="box">
    <div class="item"></div>
    <div class="item" id="item2"></div>
    <div class="item" id="item3"></div>
    <div class="item"></div>
</div>
css
.box {
    width: 700px;
    height: 400px;
    background-color: #EEB4B4;
    display: flex;
    justify-content: space-around;   
}
.item {
    width: 150px;
    height: 150px;
    font-size: 100px;
    border: 1px solid green;
    display: flex;
    justify-content: center;
    align-items: center;
}
效果

image

flex-grow 项目的放大比例

取值大致有三种情况:

默认值0,即使还存在剩余空间也不放大

所有子项目item取值都为1(或其他相同值),将等分剩余空间(如果有的话)

子项目item取值不相同,比如一个为2,其余都是1,那么属性值为2的item占据的剩余空间是属性值为1的2倍

demo

我们先来设置flex-grow属性值为1,效果如下:

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

image

将id为item2和item3的flex-grow属性值设置为2

#item2,#item3 {
   flex-grow: 2;
}

image

flex-shrink 项目的缩小比例

这个属性的效果与flex-grow是相反的,取值也有三种情况:

默认为1,即如果空间不足,该项目将缩小

所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小

子项目item取值不相同,比如一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小

demo

先增加子项目item的数量

.box {
    ...
    <div class="item">五</div>
    <div class="item">六</div>
     <div class="item">七</div>
}

然后看flex-shrink的默认值,也就是属性值为1的情况,效果如下:

image

将id为item2和item3的flex-shrink属性值设置为0

#item2,#item3 {
   flex-shrink: 0;
}

image

所以,从flex-growflex-shrink的默认值我们可以知道

flex弹性盒子在存在剩余空间的情况下是默认不具有伸缩性的,在不存在剩余空间的情况下是默认收缩的

flex-basis 定义项目占据的主轴空间(在有剩余空间的情况下)

默认值为auto,项目本身的大小,也就是说从子项目结束后那个位置开始分配项目空间

属性值为width或height属性一样的值(比如350px),代表项目将占据的空间,也就是说从子项目开始的位置分配项目空间

demo

再次将子项目item的数量设为四个,基于最上面的样式设置,给第二个item设置width:200pxflex-basis就用默认值

#item2 {
   width: 200px;
   height: 150px;
}

image

然后将子项目.item{...}添加样式flex-basis:170px;,设置具体的数值

image

可以看到是从子项目开始的位置,重新分配项目占据空间

flex flex-grow, flex-shrink 和 flex-basis的简写

同样按上面的样式设计,有四种取值情况:

默认值是0 1 auto,代表项目在有剩余空间的情况下,不具有伸缩性;在没有剩余空间的情况下,默认压缩,且从子项目结束后那个位置开始分配项目空间

image

属性值是auto (1 1 auto) ,从子项目结束的位置分配剩余空间

image

属性值是none (0 0 auto),不分配剩余空间

image

属性值是数值(比如1),这三个值分别是

image

从子项目开始的位置分配剩余空间,同flex-basis:auto的情况相反

image

通常在项目中,我们往往是在同级子项目item宽度或高度固定的情况下,让其他子项目占据剩余空间时使用flex:1

比如,在上述情况下我们只取两个子项目item,其中一个item宽度和高度固定,另一个item设置flex:1,如下;

html
<div class="box">
    <div class="item">一</div>
    <div class="item" id="item2">二</div>
</div>
css
.box {
    width: 700px;
    height: 400px;
    background-color: #EEB4B4;
    display: flex;
    justify-content: center;   
}
.item {
    width: 150px;
    height: 150px;
    font-size: 100px;
    border: 1px solid green;
    display: flex;
    justify-content: center;
    align-items: center;
}
.item2 {
    flex: 1;
}

image
可以看到设置了flex:1的子项目占据了所有的剩余空间,并始终从头布局(父元素的justify-content: center;可以相当于未生效)

封装

在项目开发中,我们尽量做到自己封装好flex这些常用的布局方法,比如封装到一个全局样式中,然后在之后的页面css中引入全局样式,具体可以查阅我之前用flex实现的H5页面'头尾固定,中间滚动'的项目,在该项目的global.css中就是我对flex布局常用属性的兼容性的全局封装

.flex {
    display: flex;
    /* 兼容性 */
    display:-webkit-box;
    display: -moz-box;
    display: -ms-flexbox;
    display: -webkit-flex;
}

.direction-column {
    -webkit-box-orient:vertical;
    -webkit-box-direction:normal;
    -moz-box-orient:vertical;
    -moz-box-direction:normal;
    flex-direction: column;
    -webkit-flex-direction:column;
}

以上情况的处理往往是我们写单个网页时。在项目中常常用插件来自动实现兼容性的处理

但是为了方便,在项目中多次用flex布局时,我们也可以对齐进行封装,比如vue,可以参考博客如果说 Flexbox 之前的布局都是错的...