CSS 基础知识 —— Flex 布局

138 阅读8分钟

前言

最近,在学习一些前端知识。在学习的过程中发现会经常使用到Flex布局,对这个知识点不太熟悉。因此,专门写一篇文章来记录一下学习历程和心得。

本文的内容参考了网上公开的资料,其中主要参考了这两个网址:CSS Flexible Box Layout Module Level 1A Complete Guide to Flexbox

什么是Flex布局

Flex布局的英文是Flexbox Layout,也可以称为Flexible Box,翻译成中文的意思就是弹性盒子,因为听上去总感觉怪怪的,所以一般我们都很少直接使用中文翻译。

Flex布局的目的是希望即使在容器内大小未知或者动态情况下,提供一种更有效的容器内布局、对齐和空间分配方式。换句话说,也就是Flex布局赋予了容器具有能够改变其内部的宽度、高度,甚至是顺序等属性,可以通过使用控制其内部的填充样式,或者使用防止其溢出。

传统的布局通常使用blockinline来表示纵向布局和水平布局。与传统的布局相比,Flex布局是一种与方向无关的布局,其优点是能够提供更好的灵活性,同时也能够支持一些大型的复杂布局,尤其是在其内部方向改变、大小重置、伸缩等情况。

基础知识

Flex布局是一个知识体系,它包括一系列的属性值。其中这些属性值中有些需要被声明在父容器上,有些需要被声明在子条目上。一个常规的Flex布局应该声明是flex和它的direction。网站[1]给出了这样一张图来描述它们之间的关系: image

容器中的所有子视图只可能沿着main axismain startmain end排列,或者是沿着cross axiscross startcross end排列,没有其他情况。结合上图,解释一下它们的含义:

  1. main axis 主轴是flex布局中默认的排列方式。但是,可以通过设置flex-direction来改变其排列方式。

  2. main-start | main-end 默认的主轴排列方式是容器中的子视图将自main-startmain-end排列。

  3. main size 所有子视图中的宽度的总和(包括内外布局等)就是容器的宽度。所有子视图中的高度的总和(包括内外布局等)就是容器的高度。

  4. cross axis 垂直于主轴的就是横轴。横轴始终与主轴保持垂直,其方向决定于主轴的方向。其实我们可以把上图看成一个罗盘,在默认情况下主轴是自西向东,那么此时的横轴就是自北向南。若主轴通过flex-direction属性更改了方向,主轴不再是自西向东,而是变成了自北向南,那么根据“横轴始终与主轴保持垂直”,横轴就变成了自西向东。

  5. cross-start | cross-end 默认的横轴排列方式是容器中的子视图将自cross-startcross-end排列。

  6. cross size 子视图的高度或者宽度就是横轴的大小。

Flex布局的属性

Flex布局的属性值有的只能在声明在容器上,有的只能声明在容器内的子条目上。如下图,最外面的矩形方框是容器,容器内部的蓝色背景色的方块是子条目。

image

声明在容器上的属性

  • display 定义一个Flex的容器,容器的条目是inline还是block取决于声明的值。

    .container {
        display: flex; /* or inline-flex */
    }
    
  • flex-direction 设置主轴main-axis的方向,目的是设置容器内子条目的排列方向。取值有四种情况,分别是rowrow-reversecolumncolumn-reverse,与图对应的关系就是:

    .container{
        flex-direction: row | row-reverse | column | column-reverse;
    }
    

    image

    • row(默认): 从左到右
    • row-reverse: 从右到左
    • column: 从上到下
    • column-reverse: 从下到上
  • flex-wrap 默认情况下,子条目会在一排显示。如果需要让其换行,可以通过这个属性来进行控制。 image

    .container{
        flex-wrap: nowrap | wrap | wrap-reverse;
    }
    
    • nowrap(默认): 不换行
    • wrap: 换行
    • wrap-reverse: 翻转换行
  • flex-flow 这个属性是flex-directionflex-wrap的组合,比如我们声明样式时,会这样写:

    .container{
        flex-direction: row;
        flex-wrap: wrap;
    }
    

    而现在,有了flex-flow这个属性,我们就可以把上面两行换成一行:

    .container{
        flex-flow: row | wrap;
    }
    
  • justify-content 定义在主轴上的每排子条目的排列方式。取值有如下几种情况:

    .container{
        justify-content: flex-start | flex-end | start | end | left | right | center | space-between | space-around | space-evenly;
    }
    
    • flex-start(默认): 沿着flex-direction的方向靠近start对齐。
    • flex-end: 沿着flex-direction的方向靠近end对齐。
    • start: 同flex-start
    • end: 同flex-end
    • left: 左对齐。
    • right: 右对齐。
    • center: 居中对齐。
    • space-between: 第一个子条目左对齐,最后一个右对齐,其余均分。
    • space-evenly: 除了子条目占据的空间外,其余所有空间进行均分。
    • space-around: 在一行中对子条目进行均分,每一个子条目的左右两边的边距相等。看上去好像感觉没有均分,这是因为第一个和最后一个的边只占了一份,而中间的有两份。就是这样: image
  • align-items 定义了子条目沿着横轴across-axis的排列方式。若想直观看到效果,可以点击这里

    .container{
        align-items: stretch | flex-start | flex-end | center | baseline;
    }
    
    • stretch(默认):元素被拉伸以适应容器。如果指定侧轴大小的属性值为'auto',则其值会使项目的边距盒的尺寸尽可能接近所在行的尺寸,但同时会遵照'min/max-width/height'属性的限制。
    • flex-start:元素位于容器的开头。
    • flex-end:元素位于容器的结尾。
    • center:元素位于容器的中心。
    • baseline:元素位于容器的基线上。如弹性盒子元素的行内轴与侧轴为同一条,则该值与'flex-start'等效。其它情况下,该值将参与基线对齐。
  • align-content 在弹性容器内的各项没有占用交叉轴上所有可用的空间时对齐容器内的各项(垂直)。容器内必须有多行的项目,该属性才能渲染出效果。

    .container {
      align-content: flex-start | flex-end | center | space-between | space-around | space-evenly | stretch | start | end;
    }
    
    • normal(默认值)没有设置任何值,就按照原始的方式进行排列。
    • flex-start元素位于容器的开头。
    • flex-end元素位于容器的结尾。
    • center:元素位于容器的中心。
    • space-between元素位于各行之间留有空白的容器内。
    • space-around元素位于各行之前、之间、之后都留有空白的容器内。
    • space-evenly:元素之间的空间左右均分。
    • stretch:元素被拉伸以适应容器。
    • start:同flex-start
    • end:同flex-end

声明在容器内子条目的属性

能够声明在子条目上的属性有:orderflex-growflex-shrinkflex-basisflexalign-self这几个常用的属性。

  • order 通常,子条目的顺序按照代码中的前后顺序进行渲染,但是在Flex布局中可以通过使用order关键字来进行子条目的重排。默认值为0,值越小,排序越靠前。值相同,则按照代码的先后顺序进行排列。

    .item {
        order: 5;
    }
    
  • flex-grow[2] grow表示“扩大,增加”的意思,也就是说当父容器的宽度大于子条目的总和时,此时说明父容器不仅能容纳所有的子条目,还有空余的空间。此时,设置了该属性值的条目就会根据设置的值进行扩展。若所有的子条目都设置成了1,那么表示所有的条目将均分扩展容器。该属性对负值无效。

    .item {
        flex-grow: 1;
    }
    
  • flex-shrink[2] shrink表示“收缩”的意思,也就是说当父容器的宽度小于子条目的总和时,此时说父容器无法容纳所有的子条目,子条目溢出了父容器。此时,设置该属性值就会根据设置的值进行收缩。

    .item {
        flex-shrink: 1;
    }
    
  • flex-basic 设置元素的宽度。若flex-basicwidth一同设置,前者会覆盖后者。

  • flex 为了简化代码,使用flex这个属性来表示flex-growflex-shrinkflex-basis这个三个属性值,其中flex-shrinkflex-basis是可选的。flex的默认值为none,此时表示flex-grow:0,flex-shrink:1flex-basis:auto

    .item {
        flex: none;
    }
    

    等同于:

    .item {
       flex-grow: 0;
       flex-shrink: 1;
       flex-basis: auto;
    }
    
  • align-self 父容器通过align-items来控制子条目的位置,若需要子条目自己控制位置,而不受限于align-items,可以通过使用align-self来设置。

    .item {
       align-self: auto | flex-start | flex-end | center | baseline | stretch;
    }
    

其值的含义与align-self类似。