Skip to content

弹性盒子(Flexbox)

弹性盒子(Flexbox)是 CSS3 引入的一种 一维布局方式,用于创建水平或垂直排列的灵活布局。它比 floatinline-block 等传统布局方式更强大,能够 自动调整子元素的大小、顺序和对齐方式,适用于 响应式设计


Flexbox 的核心概念

启用flex布局

采用了 flexbox 的区域就叫做 flex 容器。为了创建 flex 容器,我们把一个容器的 display 属性值改为 flex 或者 inline-flex。完成这一步之后,容器中的直系子元素就会变为 flex 元素。由于所有 CSS 属性都会有一个初始值,所以 flex 容器中的所有 flex 元素都会有下列行为:

  • 元素排列为一行(flex-direction 属性的初始值是 row)。
  • 元素从主轴的起始线开始。
  • 元素不会在主维度方向拉伸,但是可以缩小。
  • 元素被拉伸来填充交叉轴大小。
  • flex-basis 属性为 auto
  • flex-wrap 属性为 nowrap

这会让你的元素呈线形排列,并且把自己的大小作为主轴上的大小。如果有太多元素超出容器,它们会溢出而不会换行。如果一些元素比其他元素高,那么元素会沿交叉轴被拉伸来填满它的大小。

css
.container {
  display: flex;
}
  • display: flex; 让容器内部的所有直接子元素自动成为 Flex 项目(flex items),并按主轴方向排列。

当元素表现为 flex 框时,它们沿着两个轴(主轴和交叉轴)来布局:

  • 主轴(main axis)是沿着 flex 元素放置的方向延伸的轴(比如页面上的横向的行、纵向的列)。该轴的开始和结束被称为 main start 和 main end。主轴由 flex-direction 定义。
  • 交叉轴(cross axis)是垂直于主轴(flex 元素放置方向)的轴。该轴的开始和结束被称为 cross start 和 cross end
  • 设置了 display: flex 的父元素(在本例中是 <section>)被称之为 flex 容器(flex container)。
  • 在 flex 容器中表现为弹性的盒子的元素被称之为 flex 项flex item)(本例中是 <article> 元素。

flex 布局的核心概念

当使用 flex 布局时,首先想到的是两根轴线 — 主轴和交叉轴。主轴由 flex-direction 定义,另一根轴垂直于它。我们使用 flexbox 的所有属性都跟这两根轴线有关,所以有必要在一开始首先理解它。

主轴(flex-direction)

主轴由 flex-direction 定义,可以取 4 个值:

  • row
  • row-reverse
  • column
  • column-reverse

如果你选择了 row 或者 row-reverse,你的主轴将沿着行向延伸。 主轴图片

选择 column 或者 column-reverse 时,你的主轴会沿着页面的上下方向延伸——也就是块向

交叉轴

交叉轴垂直于主轴

所以如果你的flex-direction(主轴)设成了 row 或者 row-reverse 的话,交叉轴的方向就是沿着上下方向延伸的。 当主轴方向设置为 row 时,交叉轴的方向沿着块向延伸

如果主轴方向设成了 column 或者 column-reverse,交叉轴就是水平方向。 当主轴方向设置为 column 时,交叉轴的方向沿着行向延伸

理解主轴和交叉轴的概念对于对齐 flexbox 里面的元素是很重要的;flexbox 的特性是沿着主轴或者交叉轴对齐之中的元素。

起始线和终止线

另外一个需要理解的重点是 flexbox 不会对文档的书写模式提供假设。过去,CSS 的书写模式主要被认为是水平的,从左到右的。现代的布局方式涵盖了书写模式的范围,所以我们不再假设一行文字是从文档的左上角开始向右书写,新的行也不是必须出现在另一行的下面。

你可以在接下来的文章中学到更多 flexbox 和书写模式关系的详细说明。下面的描述是来帮助我们理解为什么不用上下左右来描述 flexbox 元素的方向。

如果 flex-direction 是 row,并且我是在书写英文,那么主轴的起始线是左边,终止线是右边。

书写英文时,主轴的起始线是左边

如果我在书写阿拉伯文,那么主轴的起始线是右边,终止线是左边。

书写阿拉伯文时,主轴的起始线是右边

在这两种情况下,交叉轴的起始线是 flex 容器的顶部,终止线是底部,因为两种语言都是水平书写模式。

之后,你会觉得用起始和终止来描述比左右更合适,这会对你理解其他相同模式的布局方法(例如:CSS Grid Layout)起到帮助的作用。

Flex 容器(父元素)的属性

父元素(Flex 容器)控制子元素的排列方式,主要涉及:

属性作用
flex-direction设置主轴方向(水平/垂直排列)
justify-content控制主轴上的对齐方式
align-items控制交叉轴上的对齐方式
align-content影响多行内容的对齐方式
flex-wrap控制是否换行

1. flex-direction(主轴方向)

用于 设置主轴的方向,即子元素排列的方向:

css
.container {
  display: flex;
  flex-direction: row;
}
说明
row横向排列(从左到右,默认)
row-reverse横向 反向排列(从右到左)
column竖向排列(从上到下)
column-reverse竖向 反向排列(从下到上)

适用于 控制 flex 容器内子元素的排列方式。


2. flex-wrap(是否换行)

虽然flexbox是一维模型,但可以使我们的flex项目应用到多行中。在这样做的时候,你应该把每一行看作一个新的flex容器。任何空间分布都将在该行上发生,而不影响该空间分布的其他行。

控制子元素 是否换行

css
.container {
  flex-wrap: wrap;
}
说明
nowrap不换行(默认)
wrap自动换行
wrap-reverse换行但反向排列

适用于 让子元素自动换行,防止溢出

参见 用 flex-wrap 实现多行 Flex 容器


3.align-content


4. justify-content(主轴对齐)

用于 控制子元素在主轴上的对齐方式

css
.container {
  justify-content: center;
}
说明
flex-start靠左(默认)
flex-end靠右
center居中
space-between两端对齐,元素之间均匀分布
space-around每个元素左右有相等间距

适用于 居中对齐左右分布等场景。


5. align-items(交叉轴对齐)

align-items用于 控制子元素在交叉轴上的对齐方式

css
.container {
  display: flex;
  align-items: center;
}
说明
flex-start顶部对齐
flex-end底部对齐
center居中对齐
baseline文字基线对齐
stretch拉伸填充整个容器(默认)

适用于 垂直居中对齐不同高度元素对齐


Flex 子项(子元素)的属性

子元素可以使用 flex 相关属性 控制大小、对齐方式和排列顺序:

属性作用
flex控制子元素大小
align-self控制单个子元素的对齐方式
order控制子元素的排列顺序

1. flex元素上的属性(自动伸缩)

flex-grow

flex-grow 若被赋值为一个正整数,flex 元素会以 flex-basis 为基础,沿主轴方向增长尺寸。这会使该元素延展,并占据此方向轴上的可用空间(available space)。如果有其他元素也被允许延展,那么他们会各自占据可用空间的一部分。

如果我们给上例中的所有元素设定 flex-grow 值为 1,容器中的可用空间会被这些元素平分。它们会延展以填满容器主轴方向上的空间。

flex-grow 属性可以按比例分配空间。如果第一个元素 flex-grow 值为 2,其他元素值为 1,则第一个元素将占有 2/4(上例中,即为 200px 中的 100px), 另外两个元素各占有 1/4(各 50px)。

flex-shrink

flex-grow属性是处理 flex 元素在主轴上增加空间的问题,相反flex-shrink属性是处理 flex 元素收缩的问题。如果我们的容器中没有足够排列 flex 元素的空间,那么可以把 flex 元素flex-shrink属性设置为正整数来缩小它所占空间到flex-basis以下。与flex-grow属性一样,可以赋予不同的值来控制 flex 元素收缩的程度——给flex-shrink属性赋予更大的数值可以比赋予小数值的同级元素收缩程度更大。

在计算 flex 元素收缩的大小时,它的最小尺寸也会被考虑进去,就是说实际上 flex-shrink 属性可能会和 flex-grow 属性表现的不一致。因此,我们可以在文章《控制 Flex 子元素在主轴上的比例》中更详细地看一下这个算法的原理。

>[!tip] 备注:  在给 flex-grow 和 flex-shrink 赋值时要注意比例。如果我们给所有 flex 元素的 flex 属性赋值为 1 1 200px ,并且希望其中一个元素可以增加到 2 倍,我们可以给该元素的 flex 属性赋值为2 1 200px。当然,你也可以选择赋值为 flex: 10 1 200px 和 flex: 20 1 200px 。

flex-basis

flex-basis 指定了 flex 元素在主轴方向上的初始大小。如果不使用 box-sizing 改变盒模型的话,那么这个属性就决定了 flex 元素的内容盒(content-box)的尺寸。

>[!tip] 备注: >当一个元素同时被设置了 flex-basis (除值为 auto 外) 和 width (或者在 flex-direction: column 情况下设置了height) , flex-basis 具有更高的优先级。

flex属性简写

你可能很少看到 flex-growflex-shrink,和 flex-basis 属性单独使用,而是混合着写在 flex 简写形式中。 Flex 简写形式允许你把三个数值按这个顺序书写 — flex-growflex-shrinkflex-basis

css
.item {
  flex: [flex-grow] [flex-shrink] [flex-basis];
}
  • flex-grow(增长比率)当有额外空间时,元素如何扩展
  • flex-shrink(收缩比率)当空间不足时,元素如何缩小
  • flex-basis(默认大小)元素的初始宽度
示例说明
flex: 1;让所有子元素平均分配空间
flex: 2;让该元素的宽度是其他元素的 2 倍
flex: 0 1 auto;默认值,不放大,允许缩小

适用于 自适应布局(比如 headermainsidebar

大多数情况下可以用预定义的简写形式。在这个教程中你可能经常会看到这种写法,许多情况下你都可以这么使用。下面是几种预定义的值:

  • flex: initial
  • flex: auto
  • flex: none
  • flex: <positive-number>

flex: initial 是把 flex 元素重置为 Flexbox 的初始值,它相当于 flex: 0 1 auto。在这里 flex-grow 的值为 0,所以 flex 元素不会超过它们 flex-basis 的尺寸。flex-shrink 的值为 1, 所以可以缩小 flex 元素来防止它们溢出。flex-basis 的值为 auto. Flex 元素尺寸可以是在主维度上设置的,也可以是根据内容自动得到的。

flex: auto 等同于 flex: 1 1 auto;和上面的 flex:initial 基本相同,但是这种情况下,flex 元素在需要的时候既可以拉伸也可以收缩。

flex: none 可以把 flex 元素设置为不可伸缩。它和设置为 flex: 0 0 auto 是一样的。元素既不能拉伸或者收缩,但是元素会按具有 flex-basis: auto 属性的 flexbox 进行布局。

你在教程中常看到的 flex: 1 或者 flex: 2 等等。它相当于flex: 1 1 0 或者 flex: 2 1 0。元素可以在 flex-basis 为 0 的基础上伸缩。


2. align-self(单个子元素对齐)

用于 单独控制某个子元素在交叉轴上的对齐方式

css
.item {
  align-self: center;
}

适用于 单个元素需要特殊对齐方式


3. order(改变子元素顺序)

默认情况下,flex 子元素按照 HTML 代码顺序 排列。但可以使用 order 更改排列顺序

css
.item {
  order: 2;
}

适用于 动态调整元素顺序,不改变 HTML 结构


参考:

评论区

欢迎留言、补充或勘误。

xiaoba.blog