弹性布局 Flexbox:从零开始学 – wiki基地


弹性布局 Flexbox:从零开始,掌握现代 CSS 布局利器

在现代网页设计中,布局是构建页面的基石。曾几何时,开发者们为了实现复杂的页面布局,不得不依赖于各种技巧,比如使用 floatdisplay: inline-block,甚至是过时的表格布局。这些方法往往伴随着各种难以解决的问题,比如浮动清除(clearfix)、垂直居中困难、以及响应式布局的复杂性。

直到 Flexbox(弹性盒子布局,Flexible Box Layout Module)的出现,这一切都发生了改变。Flexbox 是 CSS3 中引入的一种新的布局模式,它提供了一种更高效、更简洁的方式来对容器中的项目进行排列、对齐和分配空间,即使项目的尺寸未知或动态变化。它的设计目标是为容器提供强大的空间分布和对齐能力,特别是在一维方向(行或列)上进行布局。

本文将带你从零开始,一步步深入理解 Flexbox 的世界。我们将详细介绍 Flexbox 的核心概念、所有关键属性,并通过通俗易懂的解释和示例(文字描述示例效果),帮助你彻底掌握这个强大的布局工具。

第一章:理解 Flexbox 的核心概念

学习 Flexbox,首先需要理解几个基础但至关重要的概念。

1. 容器与项目 (Container and Items)

Flexbox 布局是基于“容器-项目”模型的。

  • Flex 容器 (Flex Container):应用了 display: flex;display: inline-flex; 属性的父元素。它是 Flexbox 布局的舞台,其内部的直接子元素将按照 Flexbox 规则进行布局。
  • Flex 项目 (Flex Items):Flex 容器的直接子元素。它们是舞台上的演员,会根据容器设置的规则来排列和分配空间。

记住:大多数 Flexbox 属性要么应用于容器,要么应用于项目。理解哪些属性应用于谁是掌握 Flexbox 的关键。

2. 主轴与交叉轴 (Main Axis and Cross Axis)

这是 Flexbox 中最核心,但也可能是对初学者来说最容易混淆的概念。Flexbox 布局总是沿着两个相互垂直的轴线进行:主轴和交叉轴。

  • 主轴 (Main Axis):Flex 项目沿着主轴方向排列。主轴的方向由 flex-direction 属性决定。
  • 交叉轴 (Cross Axis):与主轴垂直的轴线。

理解主轴和交叉轴的关键在于 flex-direction 属性。

  • flex-direction 设置为 rowrow-reverse 时,主轴是水平方向的(从左到右或从右到左),而交叉轴是垂直方向的(从上到下)。
  • flex-direction 设置为 columncolumn-reverse 时,主轴是垂直方向的(从上到下或从下到上),而交叉轴是水平方向的(从左到右)。

![Flexbox Axes Diagram (Concept)]
(想象一下一个矩形容器,里面有几个小矩形项目。如果项目是水平排列的,那么主轴就是水平的;如果项目是垂直排列的,那么主轴就是垂直的。交叉轴总是垂直于主轴。)

所有的对齐和空间分布属性,如 justify-contentalign-items,都是基于主轴和交叉轴来工作的。一旦你确定了主轴和交叉轴的方向,理解这些属性的作用就变得容易多了。

3. 主轴起点与终点,交叉轴起点与终点 (Main-start/end, Cross-start/end)

  • 主轴起点 (main-start)主轴终点 (main-end):项目在主轴上开始和结束的位置。
  • 交叉轴起点 (cross-start)交叉轴终点 (cross-end):项目在交叉轴上开始和结束的位置。

这些起点和终点会根据 flex-direction 和书写模式(如 LTR 或 RTL)而变化。例如,在 flex-direction: row; 和 LTR(从左到右)书写模式下,主轴起点是左边,主轴终点是右边。在 flex-direction: column; 下,主轴起点是顶部,主轴终点是底部。

4. 主轴尺寸与交叉轴尺寸 (Main Size and Cross Size)

  • 主轴尺寸 (main size):Flex 项目在主轴方向上的尺寸(宽度或高度,取决于主轴方向)。
  • 交叉轴尺寸 (cross size):Flex 项目在交叉轴方向上的尺寸。

例如,当 flex-direction: row; 时,主轴是水平的,项目的“主轴尺寸”就是其宽度,而“交叉轴尺寸”就是其高度。当 flex-direction: column; 时,主轴是垂直的,项目的“主轴尺寸”就是其高度,而“交叉轴尺寸”就是其宽度。Flexbox 的许多属性都与如何分配这些尺寸有关。

理解了这几个核心概念,我们就为学习具体的 Flexbox 属性打下了基础。接下来,我们将详细探讨作用于 Flex 容器的属性。

第二章:Flex 容器属性 (Properties for the Flex Container)

这些属性控制着 Flex 容器的整体行为,以及其内部 Flex 项目如何排列和对齐。将这些属性应用到父元素上。

1. display

这是激活 Flexbox 布局的关键属性。

  • display: flex;:将元素设置为一个块级的 Flex 容器。其内部的直接子元素将按照 Flexbox 规则布局,容器本身会像一个块级元素一样占据一行。
  • display: inline-flex;:将元素设置为一个行内的 Flex 容器。其内部的直接子元素按照 Flexbox 规则布局,容器本身会像一个行内块元素一样,可以与其他行内元素在同一行显示。

大多数情况下,你会使用 display: flex;

示例 HTML:
“`html

Item 1
Item 2
Item 3

“`

示例 CSS:
“`css
.container {
display: flex; / 或者 display: inline-flex; /
/ 其他 Flex 容器属性将在这里设置 /
}

.item {
/ Flex 项目属性将在这里设置 /
}
“`

设置 display: flex; 后,.item 元素就不再是普通的块级元素了,它们现在是 Flex 项目,会默认尝试在一行内排列。

2. flex-direction

这个属性决定了主轴的方向(也就是 Flex 项目的排列方向)。

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

示例 CSS:
css
.container {
display: flex;
flex-direction: row; /* 项目水平排列,从左到右 (默认) */
}
/* ------------------ */
.container {
display: flex;
flex-direction: column; /* 项目垂直排列,从上到下 */
}

理解 flex-direction 如何改变主轴方向至关重要,因为它会影响到后面 justify-contentalign-items 的行为。

3. flex-wrap

默认情况下,所有 Flex 项目都尝试放在一行(或一列)中,可能会导致容器溢出。flex-wrap 属性控制当项目总尺寸超出容器时,项目是否换行。

  • nowrap (默认值):Flex 项目不换行,可能会溢出容器。项目会尽力收缩以适应容器,但如果项目设置了最小尺寸或内容太多,就可能溢出。
  • wrap:Flex 项目会在需要时换行,新的一行或一列会沿着交叉轴方向排列。例如,如果主轴是水平的(row),换行后会形成多行,新行在下方。
  • wrap-reverse:Flex 项目会在需要时换行,但新的一行或一列会沿着交叉轴的反方向排列。如果主轴是水平的(row),换行后会形成多行,新行在上方。

示例 CSS:
css
.container {
display: flex;
flex-wrap: wrap; /* 项目超出宽度时换行 */
}
/* ------------------ */
.container {
display: flex;
flex-wrap: nowrap; /* 项目不换行,可能溢出 */
}

这个属性对于创建响应式布局非常有用,可以控制项目在小屏幕上自动换行。

4. flex-flow

这是 flex-directionflex-wrap 的简写属性。顺序是 flex-direction 后接 flex-wrap

示例 CSS:
css
.container {
display: flex;
flex-flow: row wrap; /* 等同于 flex-direction: row; 和 flex-wrap: wrap; */
}
/* ------------------ */
.container {
display: flex;
flex-flow: column nowrap; /* 等同于 flex-direction: column; 和 flex-wrap: nowrap; */
}

使用 flex-flow 可以让代码更简洁。

5. justify-content

这个属性定义了 Flex 项目在主轴上的对齐方式和空间分布方式。它处理的是容器中剩余空间的分配问题。

  • flex-start (默认值):项目从主轴的起点开始排列。多余空间集中在主轴的终点。
  • flex-end:项目从主轴的终点开始排列。多余空间集中在主轴的起点。
  • center:项目在主轴上居中排列。多余空间平均分布在项目的两侧。
  • space-between:项目之间平均分配空间,第一个项目与主轴起点对齐,最后一个项目与主轴终点对齐。
  • space-around:每个项目两侧都有相等的空间。注意,项目之间的空间是项目两侧空间的总和,所以项目之间的空间会比项目与容器边缘的空间大一倍。
  • space-evenly:所有项目之间以及项目与容器边缘之间的空间都相等。这是 CSS Box Alignment Module Level 3 中新增的值,现代浏览器支持良好。

示例 HTML:
“`html

Item 1
Item 2
Item 3

示例 CSS (`.container` 的属性):css
.container {
display: flex;
/ 假设 flex-direction: row; /
justify-content: center; / 项目水平居中 /
}
/ 效果描述:三个 50px 宽度的项目会在 400px 宽的容器内水平居中排列。容器左右两侧会有相等的剩余空间。/

/ —————— /
.container {
display: flex;
/ 假设 flex-direction: row; /
justify-content: space-between; / 项目水平分散对齐 /
}
/ 效果描述:Item 1 紧贴容器左侧,Item 3 紧贴容器右侧,Item 2 位于 Item 1 和 Item 3 之间,两者之间的空隙是剩余空间平均分配的结果。 /

/ —————— /
.container {
display: flex;
flex-direction: column; / 主轴变为垂直方向 /
height: 300px; / 确保容器有足够的垂直空间 /
justify-content: flex-end; / 项目垂直排列,从底部开始 /
}
/ 效果描述:三个 50px 高度的项目会在 300px 高的容器内垂直排列,并紧贴容器底部。容器上方会有剩余空间。 /
``justify-content` 是实现水平(或垂直,取决于主轴)居中和项目间空间分布的关键。

6. align-items

这个属性定义了 Flex 项目在交叉轴上如何对齐(针对单行单列的情况)。它决定了项目在与其主轴垂直方向上的位置。

  • stretch (默认值):如果项目在交叉轴上没有设置具体尺寸(例如,height: auto; 当主轴是水平时),项目将拉伸以填充整个容器的交叉轴尺寸。
  • flex-start:项目在交叉轴上从交叉轴的起点开始对齐。
  • flex-end:项目在交叉轴上从交叉轴的终点开始对齐。
  • center:项目在交叉轴上居中对齐。
  • baseline:项目根据其内容的基线对齐。

示例 HTML (同上):
“`html

Item 1
Item 2 (Higher)
Item 3

示例 CSS (`.container` 的属性):css
.container {
display: flex;
/ 假设 flex-direction: row; 主轴水平,交叉轴垂直 /
align-items: center; / 项目在垂直方向居中 /
}
/ 效果描述:三个项目,即使 Item 2 高度不同,它们都会在 150px 高的容器内垂直居中对齐。项目自身的顶部和底部距离容器的顶部和底部将有相等的空间。/

/ —————— /
.container {
display: flex;
/ 假设 flex-direction: row; /
align-items: flex-start; / 项目在垂直方向从顶部开始对齐 /
}
/ 效果描述:三个项目都将紧贴容器的顶部边缘排列。/

/ —————— /
.container {
display: flex;
flex-direction: column; / 主轴垂直,交叉轴水平 /
height: 300px;
align-items: center; / 项目在水平方向居中 /
}
/ 效果描述:三个项目垂直排列,但它们各自在 400px 宽的容器内水平居中。/
``align-items` 是实现垂直(或水平,取决于交叉轴)居中和项目在交叉轴上对齐的关键。它作用于容器内的 所有 项目,使它们作为一个整体在交叉轴上对齐。

7. align-content

这个属性定义了在有多行或多列 Flex 项目时(即 flex-wrap 属性生效且产生了多行/列)如何对齐这些行或列。它类似于 justify-content,但在交叉轴上起作用,并且是处理多余空间的属性,只不过它作用于整个“行堆”或“列堆”。

如果 Flex 容器只有一行或一列 Flex 项目(flex-wrap: nowrap;flex-wrap: wrap; 但项目没有溢出),那么 align-content 将不起作用。

  • stretch (默认值):每行或每列会拉伸以占据交叉轴上的剩余空间。
  • flex-start:所有行或列从交叉轴的起点开始堆叠。
  • flex-end:所有行或列从交叉轴的终点开始堆叠。
  • center:所有行或列在交叉轴上居中堆叠。
  • space-between:行或列之间平均分配空间,第一行/列与交叉轴起点对齐,最后一行/列与交叉轴终点对齐。
  • space-around:每行或每列的两侧都有相等的空间。

示例 HTML:
“`html

Item 1
Item 2
Item 3
Item 4
Item 5

示例 CSS (`.container` 的属性):css
.container {
display: flex;
flex-wrap: wrap; / 启用换行,以便产生多行 /
/ 假设 flex-direction: row; 主轴水平,交叉轴垂直 /
align-content: center; / 多行项目在垂直方向居中 /
}
/ 效果描述:容器宽度不足以容纳所有 80px 宽的项目在一行。项目会换行,形成多行(例如,两行,每行可能有 2-3 个项目)。align-content: center; 会将这两行或多行作为一个整体,在 300px 高的容器内垂直居中。/

/ —————— /
.container {
display: flex;
flex-wrap: wrap;
/ 假设 flex-direction: row; /
align-content: space-around; / 多行项目在垂直方向分散对齐,每行上下有空间 /
}
/ 效果描述:多行项目垂直排列。每行项目上方和下方都会有相等的空间。/
``align-contentalign-items的区别在于:align-items控制的是**一行/列内部**的项目如何在交叉轴上对齐,而align-content控制的是**多行/列之间**如何在交叉轴上分配空间和对齐。如果只有一行/列,align-items仍然有效(控制行内项目的对齐),但align-content` 无效。

至此,我们已经详细介绍了 Flex 容器的所有关键属性。接下来,我们将转向控制单个 Flex 项目行为的属性。

第三章:Flex 项目属性 (Properties for the Flex Items)

这些属性应用于 Flex 容器的直接子元素(即 Flex 项目),控制它们在容器内的具体行为,如顺序、伸缩、对齐等。

1. order

默认情况下,Flex 项目按照它们在 HTML 源代码中的顺序排列。order 属性允许你改变项目的视觉排列顺序,而无需修改 HTML 结构。

  • 接受一个整数值(正数、负数或零)。
  • 默认值为 0
  • 拥有较低 order 值的项目会排在前面,拥有较高 order 值的项目排在后面。
  • 如果多个项目有相同的 order 值,它们将按照在源代码中的顺序排列。

示例 HTML:
“`html

Item 1
Item 2
Item 3

示例 CSS (`.item` 的属性):css
.item {
/ 共同样式 /
width: 80px;
height: 50px;
margin: 5px;
}

.item:nth-child(1) { order: 2; } / Item 1 视觉上排在后面 /
.item:nth-child(2) { order: 1; } / Item 2 视觉上排在前面 /
.item:nth-child(3) { order: 3; } / Item 3 视觉上排在最后 /
“`
效果描述:尽管 HTML 顺序是 Item 1, Item 2, Item 3,但视觉上它们将按照 Item 2, Item 1, Item 3 的顺序排列。

2. flex-grow

这个属性定义了当容器沿主轴方向有剩余空间时,Flex 项目如何伸展来占据这些空间。

  • 接受一个非负数值(默认值为 0)。
  • 默认值 0 表示项目不会伸展来占用额外空间(但如果设置了 flex-shrink: 1,它仍然可能会收缩)。
  • 如果所有项目的 flex-grow 值都为 1,它们将平均分配剩余空间。
  • 如果一个项目的 flex-grow 值为 2,而其他项目为 1,那么拥有 flex-grow: 2 的项目将获得比其他项目多一倍的剩余空间。
  • 伸展是基于剩余空间的,而不是基于项目的原始尺寸。

示例 HTML (同上):
“`html

Item 1
Item 2
Item 3

示例 CSS (`.item` 的属性):css
.item {
/ 共同样式 /
height: 50px;
margin: 5px;
flex-basis: auto; / 或 80px /
}

.item:nth-child(1) { flex-grow: 1; } / Item 1 会伸展 /
.item:nth-child(2) { flex-grow: 1; } / Item 2 会伸展 /
.item:nth-child(3) { flex-grow: 1; } / Item 3 会伸展 /
``
效果描述:容器总宽度 400px。三个项目各自宽度 80px,加上默认 margin 或 gap(假设没有),总宽度 240px。剩余空间 400 - 240 = 160px。每个项目
flex-grow: 1`,它们将平均分配这 160px,每个项目额外获得 160px / 3 的宽度。它们的最终宽度会大于 80px。

css
.item:nth-child(1) { flex-grow: 1; }
.item:nth-child(2) { flex-grow: 2; } /* Item 2 伸展更多 */
.item:nth-child(3) { flex-grow: 1; }

效果描述:剩余空间 160px。总 flex-grow 值为 1+2+1=4。Item 1 获得 1/4 的剩余空间 (40px),Item 2 获得 2/4 (1/2) 的剩余空间 (80px),Item 3 获得 1/4 的剩余空间 (40px)。它们的最终宽度分别是 80+40=120px, 80+80=160px, 80+40=120px。

3. flex-shrink

这个属性定义了当容器沿主轴方向空间不足时,Flex 项目如何收缩

  • 接受一个非负数值(默认值为 1)。
  • 默认值 1 表示项目会收缩以防止溢出。
  • 0 表示项目不会收缩,即使空间不足。
  • 数值越大,项目收缩得越厉害。收缩的计算比伸展复杂一些,因为它涉及到项目的 flex-basis(或宽度/高度)以及所有项目的收缩比例之和。简单理解就是,当需要收缩时,flex-shrink 值较大的项目会承担更多的收缩量。

示例 HTML:
“`html

Item 1
Item 2
Item 3

示例 CSS (`.item` 的属性):css
.item {
/ 共同样式 /
height: 50px;
margin: 5px;
}

.item:nth-child(1) { flex-shrink: 1; } / 默认 /
.item:nth-child(2) { flex-shrink: 1; } / 默认 /
.item:nth-child(3) { flex-shrink: 1; } / 默认 /
``
效果描述:容器宽度 200px。三个项目各自宽度 100px,总宽度 300px (不计 margin)。空间不足 100px (300-200)。因为
flex-shrink` 都为 1,项目会平均收缩,每个项目宽度会小于 100px,以尝试适应容器(具体收缩量与原始尺寸有关,计算较复杂,但效果是平均收缩)。

css
.item:nth-child(1) { flex-shrink: 0; } /* Item 1 不收缩 */
.item:nth-child(2) { flex-shrink: 1; }
.item:nth-child(3) { flex-shrink: 1; }

效果描述:容器宽度 200px,项目总宽度 300px。Item 1 设置了 flex-shrink: 0;,它将保持 100px 的宽度,不会收缩。剩余的 100px 不足由 Item 2 和 Item 3 来承担。它们会收缩,各自的宽度会小于 100px(且相等),最终容器可能会溢出,因为即使 Item 2 和 Item 3 收缩到最小,加上 Item 1 的 100px 仍然可能超过 200px。

4. flex-basis

这个属性定义了 Flex 项目在分配剩余空间(通过 flex-grow)或收缩(通过 flex-shrink)之前,其在主轴方向上的初始尺寸

  • 可以是一个长度值(如 px, %, em 等),或关键字 auto (默认值)。
  • 如果设置为 auto,项目的初始尺寸由其自身的 widthheight 属性决定。如果项目本身也没有设置尺寸,则由其内容决定。
  • 如果设置为长度值,则该值将作为项目的初始尺寸,会覆盖项目本身的 widthheight 属性(除非 min-width/max-widthmin-height/max-height 限制)。

示例 HTML (同上):
“`html

Item 1
Item 2
Item 3

示例 CSS (`.item` 的属性):css
.item {
/ 共同样式 /
height: 50px;
margin: 5px;
flex-grow: 1; / 使项目伸展 /
}

.item:nth-child(1) { flex-basis: 50px; } / Item 1 初始尺寸 50px /
.item:nth-child(2) { flex-basis: 100px; } / Item 2 初始尺寸 100px /
.item:nth-child(3) { flex-basis: 150px; } / Item 3 初始尺寸 150px /
``
效果描述:项目总初始尺寸 50+100+150 = 300px。容器 400px。剩余空间 100px。因为所有项目
flex-grow: 1,它们会平均分配这 100px 空间,每个额外获得 约 33.3px。最终尺寸分别是 50+33.3=83.3px, 100+33.3=133.3px, 150+33.3=183.3px。可以看到flex-basis` 确实设定了初始宽度。

注意:当主轴是水平方向时,flex-basis 控制的是宽度;当主轴是垂直方向时,flex-basis 控制的是高度。

5. flex

这是 flex-grow, flex-shrink, 和 flex-basis 的简写属性。顺序是 flex-grow 后接 flex-shrink,最后是 flex-basis

  • 语法: flex: <flex-grow> <flex-shrink> <flex-basis>;
  • 默认值是 0 1 auto (即 flex-grow: 0; flex-shrink: 1; flex-basis: auto;)。
  • 可以使用预设值:
    • flex: auto; 等同于 1 1 auto。项目可以伸展和收缩,基于其内容尺寸。
    • flex: none; 等同于 0 0 auto。项目既不伸展也不收缩,保持其内容尺寸。
    • flex: 0 auto; 等同于 0 1 auto (即默认值)。项目不伸展,但会收缩。
    • flex: 1; 等同于 1 1 0%。这是创建等比例自适应布局非常常用的写法。项目会伸展和收缩,并且在计算伸缩时,初始尺寸被视为 0。这意味着所有设置为 flex: 1; 的项目将具有相同的最终尺寸(如果有剩余空间,它们会平均分配;如果空间不足,它们也会基于 0% 的初始尺寸按比例收缩)。

示例 CSS:
“`css
.item {
flex: 1 1 0%; / 常用等分布局 /
/ 或者简写为 flex: 1; /
}
/ 效果描述:所有设置了 flex: 1; 的项目,无论它们原本的宽度或内容多少,在有空间的情况下会平均分配剩余空间,最终倾向于等宽(或等高,取决于主轴)。/

.item {
flex: 0 0 100px; / 项目固定尺寸 100px,不伸展不收缩 /
}
/ 效果描述:项目固定宽度 100px。 /

.item {
flex: 1 0 auto; / 项目可以伸展,但不收缩,初始尺寸 auto /
}
/ 效果描述:项目宽度首先由内容或自身宽度决定。如果容器有剩余空间,项目会伸展。如果空间不足,项目不会收缩,可能导致溢出。/
``
掌握
flex` 简写属性对于写简洁高效的 Flexbox 代码非常重要。

6. align-self

这个属性允许单独控制一个 Flex 项目在交叉轴上的对齐方式,从而覆盖容器上设置的 align-items 属性。

  • 接受与 align-items 相同的值:auto (默认值,继承容器的 align-items 属性)、flex-start, flex-end, center, baseline, stretch

示例 HTML:
“`html

Item 1
Item 2
Item 3

示例 CSS (`.item` 的属性):css
.item {
/ 共同样式 /
width: 80px;
height: 50px;
margin: 5px;
}

.item:nth-child(2) {
align-self: flex-end; / 单独让 Item 2 在垂直方向底部对齐 /
}
``
效果描述:Flex 容器设置了
align-items: center;,所以 Item 1 和 Item 3 会在容器内垂直居中。但 Item 2 单独设置了align-self: flex-end;`,它会脱离整体对齐规则,单独在垂直方向底部对齐。

align-self 为我们提供了对单个项目进行微调对齐的能力,非常灵活。

第四章:实践应用:常见的 Flexbox 布局模式

掌握了 Flexbox 的属性后,让我们看看如何用它来实现一些常见的网页布局。

1. 水平导航栏

“`html

css
.navbar {
display: flex; / 激活 flex 布局 /
list-style: none; / 如果是 ul/li 移除列表样式 /
padding: 0;
margin: 0;
background-color: #f0f0f0;
}

.navbar a { / Flex 项目 /
padding: 10px 15px;
text-decoration: none;
color: #333;
}

/ 可以根据需要调整空间分布 /
.navbar {
justify-content: space-around; / 链接之间平均分布空间 /
}
/ 或者 /
.navbar {
justify-content: space-between; / 链接首尾对齐,中间分散 /
}
/ 或者 /
.navbar {
justify-content: center; / 链接整体居中 /
}
``
效果描述:导航链接会水平排列。通过调整
justify-content`,可以轻松控制链接的对齐和间隔。

2. 垂直居中任何元素

这是 Flexbox 最受欢迎的应用之一。

“`html

我要居中!

css
.parent-container {
display: flex;
justify-content: center; / 主轴(水平)居中 /
align-items: center; / 交叉轴(垂直)居中 /

/ 需要给容器一个尺寸,否则没有空间可供居中 /
width: 100vw; / 视口宽度 /
height: 100vh; / 视口高度 /
border: 1px solid red;
}

.centered-box {
/ Flex 项目无需特殊设置,它的外边距和尺寸会影响最终位置,但核心居中由父容器控制 /
width: 200px;
height: 100px;
background-color: lightblue;
}
``
效果描述:
.centered-box将在.parent-container` 的水平和垂直方向上都完全居中。

3. 相等高度的列布局

使用 Flexbox 可以轻松实现多列布局,且让所有列具有相同的高度,这是传统布局(如 float)难以做到的。

“`html

Column 1

内容较少。

Column 2

内容较多,导致高度更高。

看我,我能让所有列一样高!

Column 3

内容适中。

css
.row {
display: flex; / 使子元素(列)flex 项目 /
/ 默认 flex-direction: row; 主轴水平 /
align-items: stretch; / 默认值,项目会拉伸填充交叉轴(垂直) /
border: 1px solid green;
}

.col { / Flex 项目 /
flex: 1; / flex-grow: 1, flex-shrink: 1, flex-basis: 0% /
/ 让所有列平均分配宽度,并因为 flex-basis: 0% 倾向于等宽 /
/ 如果想固定列宽,flex: 0 0 200px; /
/ 如果想按比例分配,flex: 1; flex: 2; flex: 1; /

padding: 20px;
margin: 5px;
background-color: #eee;
border: 1px solid #ccc;
}
``
效果描述:无论每列的内容高度如何,所有
.col元素的高度都会拉伸到.row中最高那个的高度。同时,flex: 1;` 使它们在容器宽度内平均分配空间,形成等宽的三列布局(减去 margin 和 padding 的影响)。

4. 响应式布局:改变排列方向

在小屏幕上将水平排列的元素(如导航、商品列表)改为垂直排列非常常见。使用 Flexbox 结合媒体查询可以轻松实现。

“`html

A
B
C

css
.responsive-container {
display: flex;
flex-direction: row; / 默认大屏幕水平排列 /
}

.item {
flex: 1; / 平均分配宽度 /
text-align: center;
padding: 20px;
border: 1px solid #ccc;
}

/ 在屏幕宽度小于 600px 时 /
@media (max-width: 600px) {
.responsive-container {
flex-direction: column; / 小屏幕垂直排列 /
}

.item {
flex: auto; / 垂直排列时,让高度自适应内容 /
width: auto; / 垂直排列时,宽度恢复 auto /
}
}
“`
效果描述:在大屏幕上,A、B、C 会水平等宽排列。在屏幕宽度小于 600px 时,它们会自动变成垂直排列,并且高度由内容决定。

第五章:Flexbox 与 Grid 的简要对比

Flexbox 和 CSS Grid 都是强大的现代 CSS 布局模块,但它们适用于不同的场景:

  • Flexbox 适用于一维布局,即沿着一条直线(主轴)排列项目。它非常适合构建组件内部的布局,如导航条、按钮组、表单项对齐等,以及实现灵活的单行或单列布局。
  • CSS Grid 适用于二维布局,即同时在行和列两个方向上布局项目。它更适合用于构建整个页面的网格结构、复杂的卡片布局等。

你可以将 Flexbox 和 Grid 结合使用。例如,用 Grid 搭建页面的整体框架(头部、侧边栏、主内容区等),然后在主内容区或侧边栏内部使用 Flexbox 来布局其子元素(如在一个卡片中使用 Flexbox 对齐图片和文本)。

第六章:兼容性与注意事项

Flexbox 的现代语法(W3C 标准)在绝大多数现代浏览器中都有良好的支持,包括最新的 Chrome, Firefox, Safari, Edge 等。

不过,历史上 Flexbox 曾有过不同的草案版本,导致存在一些旧的、带浏览器前缀的语法(如 -webkit-box-, -ms-flexbox- 等)。对于新的项目,通常无需考虑这些旧语法,除非你需要支持非常老旧的浏览器(如 IE 9 或更早)。对于 IE 10 和 11,它们支持 Flexbox 的一个早期版本语法,有些属性或值可能行为略有不同或不支持。如果你需要支持这些浏览器,建议查阅相关兼容性资料(如 Can I Use 网站)。

在实际开发中,推荐使用 Can I Use (caniuse.com) 来查询你需要的 Flexbox 特性在目标浏览器中的支持情况。

一些注意事项:

  • 子元素的 float, clear, vertical-align 属性在 Flex 项目上将失效。 这些属性是用于传统布局模型的。
  • Margin 的合并 (margin collapsing) 不会发生在 Flex 项目之间。 这使得空间控制更加可预测。
  • 某些块级元素的特性在 Flex 项目上会改变。 例如,Flex 项目默认不会占满其交叉轴方向的整个空间(除非 align-items 设置为 stretch 且没有设置显式尺寸)。
  • 调试:使用浏览器开发者工具检查 Flex 容器和 Flex 项目的属性非常重要。大多数现代浏览器在检查元素时会显示 Flexbox 的相关信息和轴线,这对于理解和调试布局非常有帮助。

总结与展望

Flexbox 彻底改变了 CSS 布局的方式,使得创建各种灵活、响应式的布局变得前所未有的简单和直观。通过掌握容器和项目属性,理解主轴和交叉轴的概念,你可以轻松实现水平垂直居中、等高列、动态空间分配、调整项目顺序等之前繁琐的任务。

虽然 Flexbox 主要用于一维布局,但它足以应对网页中大部分组件级别的布局需求。结合 CSS Grid 进行页面整体布局,你将拥有构建任何复杂现代网页布局所需的强大工具集。

从零开始学习 Flexbox 可能需要一些时间来适应主轴和交叉轴的概念,以及每个属性的具体作用。最好的学习方法是:

  1. 动手实践: 创建一个 Flex 容器和几个项目,逐一尝试每个属性,观察其效果。
  2. 利用开发者工具: 使用浏览器调试工具查看 Flexbox 布局,理解属性如何影响元素的尺寸和位置。
  3. 参考文档和教程: MDN Web Docs 提供了非常详细和准确的 Flexbox 文档,是学习和查阅的好资源。
  4. 解决实际问题: 尝试使用 Flexbox 重构你之前用传统方法实现的布局,或者解决你在实际开发中遇到的布局难题。

Flexbox 是现代前端开发者的必备技能之一。投入时间去学习和掌握它,你的布局工作将变得更加高效、愉快,并且能够轻松应对各种设备和屏幕尺寸的挑战。现在,就从创建一个简单的 display: flex; 容器开始,探索弹性布局的无限可能吧!

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部