CSS FlexBox布局全面详解

459 阅读8分钟

1. 什么是FlexBox

FlexBox(”弹性布局”)是CSS3提供的用于布局的一套新属性,这套属性包括针对容器(弹性容器,flex container)和针对其直接子元素(弹性项,flex item)的两类属性

FlexBox可以控制弹性项(flex item)的以下方面:

  • 大小,基于内容和可用空间
  • 流动方向,水平还是垂直,正向还是反向
  • 两个轴向的对齐和分布
  • 顺序,可覆盖源代码中的顺序

在这里插入图片描述 flex container默认存在两根轴:水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴(横轴)的开始位置(与边框的交叉点)叫做main start,结束位置叫做main end;交叉轴(竖轴)的开始位置叫做cross start,结束位置叫做cross end。

flex item默认沿主轴排列。单个项目占据的主轴空间叫做main size,占据的交叉轴空间叫做cross size。

FlexBox布局在很大程度上解决了行内块,浮动以及表格布局中的各种问题和缺点。如今,随着各浏览器对Flex布局兼容性的完善,无论是PC端还是移动端页面,它都应是主流布局方案

2. 容器(flex container)

.flex-container{
        display: flex;
    }
<div class="flex-container">
    <span>flex item</span>
    <div>flex item</div>
    <p>flex item</p>
</div>

对于任意类型的元素定义display:flex后,该元素就会变成容器flex container。此时,它的所有的直接子元素(无论什么元素类型)都会变成弹性项flex item

成为flex container的元素可设置以下CSS属性:

(1) flex-direction flex-direction 决定主轴的方向(即flex item的排列方向)。它有4个可能的值 :

row(默认值):主轴为水平方向,起点在容器的左端。

在这里插入图片描述 row-reverse:主轴为水平方向,起点在容器的右端。

在这里插入图片描述 column:主轴为垂直方向,起点在容器的上沿。

在这里插入图片描述 column-reverse:主轴为垂直方向,起点在容器的下沿。

在这里插入图片描述 (2) flex-wrap

默认情况下容器里的所有flex item都排在一条线上,flex-wrap定义如果一行排不下如何换行。它可能的值有三个:

nowrap(默认):不换行,此时超出一行,则每个flex item按照一定规则进行比例收缩。

在这里插入图片描述 wrap:换行,第一行在上方(即从左往右,从上往下的顺序)。

在这里插入图片描述 wrap-reverse:换行,第一行在下方(即从左往右,从下往上的顺序)。 在这里插入图片描述

(3) flex-flow

flex-flow属性是flex-direction属性和flex-wrap属性的简写形式,默认值为row nowrap。

(4) justify-content

justify-content 定义了flex item在主轴(横轴)上的对齐方式。它可能的值有5个:

  • flex-start(默认值):左对齐
  • flex-end:右对齐
  • center: 居中
  • space-between:两端对齐,flex item之间的间隔都相等(如果只有两个flex item则主轴两边各一个。如果只有一个flex item则只在容器主轴的开始位置排列 )。
  • space-around:每个flex item两侧的间隔相等。所以,flex item之间的间隔比主轴两边的flex item到左,右边界的间隔大一倍(如果只有一个flex item则排列在中间)。

在这里插入图片描述 (5) align-items

align-items 定义了flex item在交叉轴(纵轴)上的对齐方式。它可能的值有5个:

  • stretch(默认值):如果项目未设置高度或设为auto,将占满整个容器的高度。
  • flex-start:交叉轴的起点对齐。
  • flex-end:交叉轴的终点对齐。
  • center:交叉轴的中点对齐。
  • baseline: 项目的第一行文字的基线对齐。

在这里插入图片描述 (6) align-content

align-content属性定义了多根轴线(即多行)的对齐方式。如果项目只有一根轴线(一行),该属性不起作用。

  • stretch(默认值):轴线占满整个交叉轴。
  • flex-start:与交叉轴的起点对齐。
  • flex-end:与交叉轴的终点对齐。
  • center:与交叉轴的中点对齐。
  • space-between:与交叉轴两端对齐,轴线之间的间隔平均分布。
  • space-around:每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。

在这里插入图片描述 垂直居中技巧

给flex contanier设置justify-content:center和align-items:center可实现所有flex item的相对于flex contanier的垂直水平居中

3. 弹性项(flex item)

成为弹性项的元素可以设置以下CSS属性:

(1)order

order属性定义flex item的排列顺序。数值越小,排列越靠前。默认情况下每个flex item 为0,表示就按照HTML代码定义的弹性项元素顺序排列。该值可为正数和负数

虽然order的自定义设置可以实现覆盖源代码中HTML元素的渲染顺序,但实际编写时还是应该要按逻辑顺序来,因为键盘的Tab切换和屏幕阅读器不会受order属性的影响

(2)flex grow

flex-grow属性定义flex item的放大比例,默认为0,即如果存在剩余空间,也不放大。不可为负值。

默认情况下,每个flex item的实际宽度由width属性决定(若未设置则由自身内容决定);如果设置了flex-grow的值不为0,那么该属性的效果将会覆盖width设置的效果

举例:

如果所有flex item的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。设此时每个flex item的flex grow为x,则各自宽度分别占据容器宽度的x / 所有flex item的x累加值

在这里插入图片描述 (3)flex-shrink

flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。不可为负值 在这里插入图片描述

如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。

(4)flex-basis

flex-basis属性定义了在分配多余空间之前,flex item占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即flex item的本来大小。

在一定程度下,你可以把这个属性理解为flex item的初始width或者说就当作width属性。与width同理,即使设置了flex-basis,flex item的最终实际宽度同样会受flex-grow和flex-shrink影响(当flex容器空间充足或不足时,使flex item可以超出或不满足flex-basis定义的宽度时就会根据felex-grow和flex-shrink的比例进行放大或缩小)

当width,flex-basis同时存在时,flex-basis优先级更高

(5)flex

flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值按顺序分别为为0 1 0%。后两个属性可选。

如果flex属性值仅有一个数值(如flex:1),则其代表flex-grow的值,此时flex:1等价于flex:1 1 0%

flex:0等价于flex:0 1 0%(只许缩小,不许放大) flex:none等价于flex:0 0 auto(既不缩小也不放大) flex:auto等价于flex:1 1 auto(能小就小,能大就大)

建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。

(6)align-self

align-self属性允许单个flex item有与其他flex item不一样的纵轴对齐方式,可覆盖align-items属性。其可选值与align-items一致,默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。

在这里插入图片描述

收缩flex item的规则

在flex item总宽度超出容器一行的宽度且设置不换行(flex -wrap:nowrap)的情况下,默认每个flex item会根据自身的flex-basis系数和flex-shrink值按比例收缩,而不是误解为“每个flex item会根据超出的总宽度来平均分配,收缩相同的宽度”。我们需要记住的是根据flex-shrink来收缩的规则和根据flex-grow来放大的计算规则是不一样的即可

扩展技巧

如果指定某一个flex item的某侧的margin为auto,并且flex container的那一侧还有空间,那么该侧的外边距就会扩展占据可用空间

利用这个特点,可以应用以下场景:

(1)实现某个flex item位于一侧,其他flex tiem位于另一侧的布局

在这里插入图片描述

<div class="flex-container">
   <div></div>
    <div></div>
    <div></div>
</div>
    .flex-container{
        display: flex;
        width: 500px;
        height: 300px;
        background-color: green;
    }
    .flex-container>div{
        width: 100px;
        height: 100px;
        background-color: red;
        border:1px solid #cccccc
    }
    .flex-container>div:first-child{
    /*让第一个flex item位于左侧并外边距占据剩余空间*/
        margin-right: auto;
    }

(2)另一种风格的“垂直水平居中” 在这里插入图片描述

   .flex-container{
        display: flex;
        width: 500px;
        height: 300px;
        background-color: green;
    }
    .flex-container>div{
        width: 100px;
        height: 100px;
        background-color: red;
        border:1px solid #cccccc;
        margin:auto;
    }

注意:这种垂直水平居中方案与严格意义的水平垂直居中不同的是,每个flex item之间的距离以及相对左,右边界的距离会基于剩余空间进行平均分配。一般情况下,每个flex item之间的距离是两侧的flex tem到对应边界距离的2倍

4. 其他细节

  • flex item即使被指定可收缩,但其会存在一个“隐性最小宽度”,换句话说它不会无限收缩。可通过设置min-width属性来覆盖控制这个最小宽度。同理,我们也可以通过设置max-width来控制flex item的放大上限。
  • flex item在不用设置非static的定位值的情况下亦可使用z-index属性,此时该值会覆盖堆叠次序,并创建一个新的堆叠上下文