前端必备CSS布局之弹性(Flex)布局

302 阅读11分钟

前言

《前端必备CSS之位置篇(文档流、定位与浮动)》这篇文章中,我们回顾了在弹性布局和Grid布局问世之前,占据主导地位的文档流、定位与浮动,而更具灵活性的弹性(Flex)布局和Grid布局现在已经几乎取代了浮动(float)的地位。接下来,我将带你一套通关其中的弹性布局,掌握现代CSS布局的半壁江山。

一、什么是弹性布局?

定义

弹性布局(Flexible Box Layout,简称 Flex 布局)是 CSS3 引入的一种一维布局模型,专门用于解决容器内元素的对齐、分布和自适应问题。它通过display: flexdisplay: inline-flex将容器设置为 “弹性容器”其内部子元素成为 “弹性项目”,并通过容器和项目的属性控制项目的排列规则。

  • 注意
    • 只有弹性容器的直接子元素才会自动成为弹性项目,孙子元素不直接受影响,它属于另一个层级。
    • 它们的布局默认由正常的文档流(或其他布局方式,如自身的 flex 设置)控制,与外层弹性容器的 flex 属性无关(除非将孙子元素所在的弹性项目设置为新的弹性容器)。
  • 核心概念
    • 弹性容器(Flex Container) :设置 display: flex(块级弹性容器) 或 display: inline-flex(行内级弹性容器) 的父元素。
    • 弹性项目(Flex Item) :弹性容器的直接子元素(孙子元素不直接受影响)。
    • 主轴(Main Axis) :项目默认沿主轴排列(方向由 flex-direction 决定)。
    • 交叉轴(Cross Axis) :垂直于主轴的轴线(方向由主轴决定)。

弹性布局示图

弹性布局各部分情况如下图所示。

弹性布局示图.jpg

二、弹性布局属性

弹性布局的属性分为弹性容器属性弹性项目属性,分别掌控弹性容器和弹性项目的显示效果。下面我们将分别介绍它们。

  • 弹性容器核心属性
    • flex-direction:决定主轴方向(项目排列方向)
    • flex-wrap:控制项目是否换行
    • flex-flowflex-direction + flex-wrap 的简写
    • justify-content:控制项目在主轴上的对齐方式
    • align-items:控制项目在交叉轴上的对齐方式(单行 / 单列时)
    • align-content:控制多根轴线在交叉轴上的对齐方式(多行 / 多列时)
  • 弹性项目核心属性
    • flex-grow:项目的扩展比例(主轴方向剩余空间分配)
    • flex-shrink:项目的收缩比例(主轴方向空间不足时收缩)
    • flex-basis:项目在主轴上的初始尺寸(默认值 auto
    • flexflex-grow + flex-shrink + flex-basis 的简写
    • order:控制项目的排列顺序
    • align-self:单个项目在交叉轴上的对齐方式(覆盖容器 align-items

(一)弹性容器属性

容器属性用于控制项目的整体排列规则,它有六个核心属性,如下所示。

1. flex-direction

flex-direction决定主轴方向(容器中的项目排列方向)。

  • 核心值

    • row(默认):主轴水平,项目从左到右排列。
    • row-reverse:主轴水平,项目从右到左排列。
    • column:主轴垂直,项目从上到下排列。
    • column-reverse:主轴垂直,项目从下到上排列。
  • 示图

    flex-direction示例.jpg

  • 示例代码

2. flex-wrap

flex-wrap控制项目是否换行,否则默认情况下,就算容器内的弹性项目宽度之和超过了容器宽度,也不会进行换行,而是会被容器自动压缩在主轴上面,排成一行。

  • 核心值

    • nowrap(默认):不换行,项目可能被挤压。
    • wrap:换行,超出部分向下换行(交叉轴方向延伸)。
    • wrap-reverse:换行,超出部分向上换行。
  • 示图

    flex-wrap示例.jpg

  • 示例代码

3. flex-flow

flex-flowflex-direction + flex-wrap 的简写,相当于同时声明了上面的 flex-direction 以及flex-wrap 两个属性

  • 语法flex-flow: <flex-direction> <flex-wrap>(默认 row nowrap)。
  • 示例
    • 示图flew-flow示例.jpg
    • 示例代码

4. justify-content

justify-content控制项目在主轴上的对齐方式。

  • 核心值
    • flex-start(默认):左对齐。
    • flex-end:右对齐。
    • center:居中对齐。
    • space-between:两端对齐,项目间距相等(首尾项目贴边)。
    • space-around:项目两侧间距相等(首尾项目距边缘为中间间距的一半)。
    • space-evenly:项目间距和首尾距边缘完全相等。
  • 示例(以主轴水平为例)
    • 示图justify-content示例.jpg
    • 示例代码

5. align-items

align-items控制项目在交叉轴上的对齐方式(单行 / 单列时)。

  • 核心值
  • stretch(默认):项目高度拉伸至与容器等高。
  • flex-start:顶端对齐。
  • flex-end:底端对齐。
  • center:居中对齐。
  • baseline:项目基线(文字底部)对齐。
  • 示例(以交叉轴垂直为例)
    • 示图align-items示例.jpg
    • 示例代码

6. align-content

align-content控制多根轴线在交叉轴上的对齐方式(多行 / 多列时)。

  • 注意:仅当项目换行(flex-wrap: wrap)且产生多根轴线时有效。
  • 核心值
    • stretch(默认):轴线拉伸至填满容器(前提是子元素没有设置固定宽或者高,比如如果手动设置了子元素的高50px,就会覆盖stretch,子元素按照手动设置的尺寸显示)。
    • flex-start:所有轴线顶端对齐。
    • flex-end:所有轴线底端对齐。
    • center:所有轴线居中对齐。
    • space-between:轴线两端对齐,轴线间距相等。
    • space-around:轴线两侧间距相等。
  • 示例
    • 示图flex-content示例.jpg
    • 示例代码

(二)弹性项目属性

项目属性用于控制单个项目的表现,和弹性容器一样,它也有六个核心属性,如下所示。

1. flex-grow

flex-grow负责控制项目的扩展比例(主轴方向剩余空间分配),也就是我们常用的按比例分配,但是比我们手动输入百分比要准确且方便的多,毕竟有时候得到的小数是除不尽的(比如1/3,我们如果手动输入33.3%还是会有误差,但是设置成1:1:1就不会了)。

  • 取值规则: 默认为0,即为不进行扩展,要求输入值必须是非负数字
  • 分配规则:分配完项目空间之后,容器内剩余空间按各项目flex-grow 设置的比例分配。
  • 示例:下面是一个1:1:1的分配示例,容器宽度800px,而项目宽度设定为100px,分配完设定的项目宽度后,剩余的500px被按照比例分配给各项目。
    • 效果示图

      flex-grow示例1.jpg

    • item1扩展示图

      flex-grow示例2.jpg

    • item2扩展示图

      flex-grow示例3.jpg

    • item3扩展示图

      flex-grow示例4.jpg

    • 扩展逻辑:容器宽度为800px,内有三个宽度为100px的弹性项目,分配完项目的空间之后,容器内还剩下500px的空间用于分配扩展空间,由于比例为1:1:1,所以每个弹性项目各分到三分之一,即500px / 3≈166.67px

    • 示例代码

2. flex-shrink

flex-shrink负责控制项目的收缩比例(主轴方向空间不足时收缩)。这个我们在前面未开启换行时,就经常碰到这个情况,容器内的项目被自动压缩至一行。

  • 取值规则:默认为1,即为允许收缩(与flex-grow相反),要求输入值必须是非负数字。
  • 搜索规则:空间不足时,项目按 flex-shrink 比例收缩(0 表示不收缩)。
  • 示例: 现在有一个宽度为800px的弹性容器,内有三个宽度为300px的弹性项目,很明显容器空间不足,将会进行收缩。
    • 效果示图

      flex-shrink示例1.jpg

    • item1收缩示图

      flex-shrink示例2.jpg

    • item2不收缩示图

      flex-shrink示例3.jpg

    • item3收缩示图

      flex-shrink示例4.jpg

    • 收缩逻辑:由于容器只有800px,三个弹性项目初始设置宽度都有300px,所以有100px的空间缺口,需要压缩容器内的弹性项目,把这要压缩的100px按收缩比例分配给item1以及item3item2flex-shrink为0,不参与收缩)。

      • item1以及item3的原width减去分配到的收缩空间,得到最终显示的宽度。
      • 其中item1 1份,item3 2份,item1收缩 100px/3≈33.33pxitem3收缩 100px * 2/3≈66.67px
    • 示例代码

3. flex-basis

flex-basis负责控制项目在主轴上的初始尺寸(默认值 auto),其优先级比width或者height高。

  • 作用规则:定义项目未扩展 / 收缩前的基础尺寸(优先级高于 width/height,即会覆盖width或者height的设置)。

    • 具体覆盖谁要看主轴方向
      • 主轴方向为水平:覆盖width
      • 主轴方向垂直:覆盖height
  • 取值规则:默认为auto(由内容或 width 决定),也可以设置为具体尺寸(如100px50%,将会覆盖width或是height),同样必须为非负数

  • 示例:设置一个容器宽度为300px,内有三个弹性项目。

    • 效果示图

      flex-basis示例1.jpg

    • item1示图:

      flex-basis示例2.jpg

    • item2示图:

      flex-basis示例3.jpg

    • item3示图:

      flex-basis示例4.jpg

    • 示例代码

4. flex

flexflex-grow + flex-shrink + flex-basis 的简写,相当于同时声明了这三个属性。

  • 语法flex: <flex-grow> <flex-shrink> <flex-basis>(默认 0 1 auto)。
  • 常用简写flex还能再进一步简写。
    • flex: auto:等价于 1 1 auto(允许扩展和收缩,基础尺寸自动)。
    • flex: none:等价于 0 0 auto(不扩展不收缩,基础尺寸自动)。
    • flex: 1:等价于 1 1 0%(常用作 “等分空间”)。
  • 示例(等分空间):以我们常用的 “等分空间” 为例。
    • 为什么设置basis: 0%:因为等分空间的重点就在于消除自身内容尺寸的干扰,将自身初始尺寸占比设为0%,使得分配空间时,能够完全按照比例分配全部可用空间

    • 示图:容器被等分为三部分等宽的空间。

      flex效果图.jpg

    • 示例代码

5. order

order控制项目的排列顺序,与优先级的设置相反,order的值越小,排序越靠前

  • 取值规则:默认为0,必须为整数(可以为负值)。
  • 示例
    • 示图order示例.jpg
    • 示例代码

6. align-self

align-self负责控制单个项目在交叉轴上的对齐方式(手动设置之后会覆盖容器 align-items)。

  • 取值规则:取值规则和容器属性align-item一样,但是默认为auto(表示继承容器的align-items,手动设置之后会覆盖容器 align-items
  • 核心值:和容器 align-items一样,但是默认值为auto
    • auto(默认):继承容器的align-items值。
    • stretch:项目高度拉伸至与容器等高。
    • flex-start:顶端对齐。
    • flex-end:底端对齐。
    • center:居中对齐。
    • baseline:项目基线(文字底部)对齐。
  • 示例
    • 示图

      align-self示例.jpg

    • 示例代码

三、弹性布局实战篇

弹性布局需要结合实战来理解,所以我将列举一些常见的弹性布局。

1. 四合院布局(语义化)

适用范围最广的四合院布局,并且通常会结合HTML5的语义化标签,即为一个Header、左右共两个Aside、一个Main、一个Footer

  • 示图

    四合院布局.jpg

  • 示例

    • 效果图

      四合院布局.gif

    • 示例代码

2. 导航栏布局

还有无论何时都居中显示的顶部导航栏布局。

  • 示图

    导航栏.gif

  • 示例代码

3. 基于弹性布局的卡片网格布局

网站中的信息很多都是以卡片的格式网格状展示,所以这个也是个常用的布局方式。

  • 示图

    卡片网格布局.gif

  • 示例代码

4. 单侧边栏

很多网站都是单侧边栏(比如左边显示目录),右边主内容区,相当于简化了四合院布局。

  • 示图

    单侧边栏布局.gif

  • 示例代码

结语

弹性布局(Flexbox)作为 CSS3 的里程碑式特性,彻底改变了前端布局的开发模式。它通过简洁的 API 解决了传统布局中 “垂直居中”、“等高列” 等经典难题,让响应式设计变得触手可及。随着浏览器兼容性的全面提升,弹性布局已成为前端工程师的必备技能,而浮动已成弃子。

这篇文章只能算是 CSS 布局的半壁江山,因为还有一半江山在 Grid 布局那里,它涉及到更复杂的二维排版,而弹性布局是一维排版,我们下次再讲 Grid 布局,精彩仍在继续哦。

如果这篇文章有帮助到你,不胜荣幸;如果文章有错误或者缺漏,请在评论区指出,大家一起进步,谢谢🙏。