Dark Dwarf Blog background

Flexbox

Flexbox

1. Flexbox 简介

Flexbox 是一种现代 CSS 布局模型,旨在提供一种更高效的方式来对容器中的项目进行布局、对齐和空间分配。它允许项目在可用空间内“伸缩”(flex),以适应不同尺寸的屏幕。

Flexbox 由如下组件构成:

  • Flex 容器 (Flex Container):应用了 display: flex; 的父元素。
  • Flex 项目 (Flex Item):Flex 容器的直接子元素。

一个元素既可以是 Flex 项目,也可以是其内部元素的 Flex 容器,这种嵌套是构建复杂布局的基础:

alt text

要将一个元素变为 Flex 容器,只需设置其 display 属性:

.container {
  display: flex;
}

2. Flex 项目的尺寸控制

Flex 项目的尺寸由三个属性共同决定:flex-growflex-shrinkflex-basis。这三个属性通常通过简写属性 flex 来设置。

a.a. flex 简写属性

flex 属性是控制 Flex 项目尺寸最核心的工具。其语法为: flex: <flex-grow> <flex-shrink> <flex-basis>;

  • flex: 0 1 auto; (默认值): 项目不放大,但会根据需要收缩,基准尺寸由其自身 width/height 决定。
  • flex: 1;: 常用简写,等同于 flex: 1 1 0;。项目会平均分配多余空间,并且在空间不足时会收缩。
  • flex: auto;: 等同于 flex: 1 1 auto;。项目会放大以填充空间,也会收缩,基准尺寸是 auto
  • flex: none;: 等同于 flex: 0 0 auto;。项目完全不具备弹性,既不放大也不收缩,其尺寸由 width/height 决定。

b.b. flex-grow:放大系数

该属性定义了当容器存在剩余空间时,项目应如何分配这些空间。

  • :一个无单位的数字,代表分配比例。
  • flex-grow: 1;:所有项目将平均分配剩余空间。
  • flex-grow: 2;:该项目获得的剩余空间将是 flex-grow: 1; 的项目的两倍。
  • 默认值0,表示项目不放大。
alt text

c.c. flex-shrink:收缩系数

该属性定义了当容器空间不足时,项目应如何收缩。

  • :一个无单位的数字,代表收缩比例。
  • flex-shrink: 1; (默认值):所有项目将按相同比例均匀收缩。
  • flex-shrink: 0;:项目不会收缩,保持其原始尺寸。
alt text

需要注意的是:当我们指定 flex-growflex-shrink 时,flex 项目不一定遵循我们设定的宽度值。在上面的例子中,三个 div 都被赋予了250px的宽度,但当它们的父容器足够大时,它们会扩展以填满空间。同样地,当父容器过小时,默认行为是它们会收缩以适应。

d.d. flex-basis:基准尺寸

该属性定义了在进行空间分配(放大或收缩)之前,项目的初始主尺寸(main size)。

  • flex-basis: auto; (默认值):项目的基准尺寸由其 widthheight 属性决定。如果内容尺寸更大,则以内容尺寸为准。
  • flex-basis: 0;:项目的基准尺寸为 0。在计算空间分配时,项目尺寸从 0 开始增长,这通常会导致它们忽略自身的 widthheight 设置。
  • flex-basis: <value>;: 可以设置为任何长度单位 (如 200px, 50%)。

3. Flexbox 轴线与换行

Flexbox 布局基于两个轴:主轴 (Main Axis)交叉轴 (Cross Axis)

a.a. flex-direction:主轴方向

flex-direction 属性决定了主轴的方向,从而控制了 Flex 项目的排列方式。

  • row (默认值):主轴为水平方向(从左到右)。
  • row-reverse: 主轴为水平方向(从右到左)。
  • column: 主轴为垂直方向(从上到下)。
  • column-reverse: 主轴为垂直方向(从下到上)。

flex-direction 改变时,与轴相关的属性行为也会改变。

  • flex-direction: row 时,flex-basis 对应 width
  • flex-direction: column 时,flex-basis 对应 height

b.b. flex-wrap:项目换行

该属性定义了当 Flex 项目在一条轴线上排不下时,是否换行。

  • nowrap (默认值):所有项目排在一条线上,可能会溢出容器。
  • wrap: 项目会从上到下自动换行。
  • wrap-reverse: 项目会从下到上自动换行。

c.c. flex-flow:方向与换行的简写

这是 flex-directionflex-wrap 的简写属性。

.container {
  /* 等同于 flex-direction: row; flex-wrap: wrap; */
  flex-flow: row wrap;
}

4. 对齐 (Alignment)

Flexbox 提供了强大的对齐功能,可以精确控制项目在主轴和交叉轴上的位置。

a.a. justify-content:主轴对齐

该属性用于对齐 Flex 项目在主轴上的排列。

  • flex-start (默认值):项目向主轴起点对齐。
  • flex-end:项目向主轴终点对齐。
  • center:项目在主轴上居中。
  • space-between:项目均匀分布,首个项目在起点,末个项目在终点,项目之间间距相等。
  • space-around:项目均匀分布,每个项目两侧的间距相等。因此,项目之间的间距是首尾项目与容器边缘间距的两倍。
  • space-evenly:项目均匀分布,所有项目之间以及项目与容器边缘之间的间距都完全相等。

b.b. align-items:交叉轴单行对齐

该属性用于对齐 Flex 项目在交叉轴上的排列。它只在项目只有一行时生效。

  • stretch (默认值):如果项目未设置高度(或宽度,取决于 flex-direction),则拉伸以填满容器的交叉轴。
  • flex-start:项目向交叉轴起点对齐。
  • flex-end:项目向交叉轴终点对齐。
  • center:项目在交叉轴上居中。
  • baseline:项目根据其内容的基线对齐。

c.c. align-content:交叉轴多行对齐

当 Flex 项目有多行时(即 flex-wrap: wrap; 生效时),align-content 用于定义这些行在交叉轴上的对齐方式。

  • stretch (默认值):各行会拉伸以填满剩余空间。
  • flex-start: 所有行都堆积在交叉轴的起点。
  • flex-end: 所有行都堆积在交叉轴的终点。
  • center: 所有行都集中在交叉轴的中间。
  • space-between: 行与行之间平均分布,第一行在起点,最后一行在终点。
  • space-around: 每行两侧的间距相等。

d.d. align-self:单个项目的交叉轴对齐

这个属性允许单个 Flex 项目覆盖其父容器的 align-items 设置。

.container {
  display: flex;
  align-items: flex-start;
}

.special-item {
  /* 这个项目将覆盖父容器的 align-items 设置,在交叉轴上居中 */
  align-self: center;
}

e.e. gap:项目间距

gap 属性是为 Flex 项目之间创建间距的现代、简洁的方法,它同时适用于行和列。

.container {
  display: flex;
  flex-wrap: wrap;
  gap: 16px; /* 在所有项目之间(水平和垂直方向)创建16px的间距 */
  /* 也可以分别设置 row-gap 和 column-gap */
}

f.f. 完美居中技巧

要在一个容器内同时实现水平和垂直居中,只需将 justify-contentalign-items 都设置为 center

.container {
  display: flex;
  justify-content: center; /* 主轴(水平)居中 */
  align-items: center;    /* 交叉轴(垂直)居中 */
  height: 100vh; /* 示例:让容器填满视口高度 */
}

5. 排序与顺序

a.a. order 属性

order 属性允许我们改变 Flex 项目的视觉顺序,而无需修改 HTML 源代码。

  • :一个整数,默认为 0
  • 数值越小的项目排得越靠前。可以为负数。
.item-1 { order: 2; }
.item-2 { order: 1; } /* item-2 会显示在 item-1 前面 */
.item-3 { order: 3; }