A Complete Guide to Flexbox

Leo
Leo
Cover Image for A Complete Guide to Flexbox
  1. 背景知识:
  2. 基础知识和术语
  3. Flexbox 属性
  4. 父元素(flex container)的属性
  5. 子元素(flex items)的属性

背景知识:

弹性盒(Flexible Box)布局旨在提供一种更有效的方法来布置、对齐和分配容器中子元素之间的空间,即使它们的大小是未知的或动态的(因此使用了“flex”这个词)。

弹性布局的主要思想是给容器赋予改变其子元素的宽度/高度(和顺序)以最好地填充可用空间的能力(主要是为了适应各种显示设备和屏幕尺寸)。

最重要的是,弹性盒布局是无方向性的,而不像常规布局(块状布局是基于垂直方向的,行内布局是基于水平方向的)。虽然这些常规布局适用于页面,但是当开发大型或复杂应用程序时不够灵活(特别是当涉及到方向更改、调整大小、伸展、缩小等方面)。

基础知识和术语

由于弹性盒布局是一个完整的模块而不是单一属性,它的全部属性会涉及到很多方面。其中一些属性是针对容器(父元素,称为“flex container”)的,而另一些属性是针对子元素(称为“flex items”)的。

如果“常规”布局基于块和行内流方向,那么弹性布局则基于“弹性流方向”。下面的这张图解释了弹性布局的主要思想。

css-terminology

子元素项目将沿着主轴(从主起始点到主结束点)或交叉轴(从交叉起始点到交叉结束点)进行布局。

  • 主轴 - 主轴(main axis)是flexbox 容器的一个属性,它是沿着其上面放置 flex 项目的主要方向。请注意,它不一定是水平的;它取决于 flex-direction 属性(见下文)。
  • 主起始点 | 主结束点 - 弹性项目需要布局在容器的主起始点和主结束点之间。
  • 主尺寸 - 弹性项目在主维度上的宽度或高度是其主尺寸。弹性项目的主尺寸是其是宽度”或“高度”属性中的一个,取决于主维度(也就是主轴的方向)。
  • 交叉轴 - 垂直于主轴的轴称为交叉轴。它的方向取决于主轴方向。
  • 交叉起始点 | 交叉结束点 - 在 Flexbox 中,交叉轴的起始位置是 Flex 容器中的左侧或顶部(取决于主轴方向),结束位置是 Flex 容器中的右侧或底部。Flexbox 中的元素按照主轴方向排列,当在交叉轴方向上需要分行时,Flexbox 会自动将元素分成多行,每行称为一个“Flex line”。这些 Flex lines 会依次填满 Flex 容器,从交叉轴的起始位置开始,一直填充到交叉轴的结束位置。
  • 交叉尺寸 - 在弹性布局中,交叉尺寸(cross size)是指沿着交叉轴的尺寸,即与主轴垂直的方向的宽度或高度。一个项目的交叉尺寸由它在交叉轴上的宽度或高度决定,它的属性由它在交叉轴上的尺寸属性(width 或 height)来决定。如果一个项目在交叉轴上的尺寸属性是 width,那么它的交叉尺寸就是它的宽度,反之如果在交叉轴上的尺寸属性是 height,那么它的交叉尺寸就是它的高度。

Flexbox 属性

父元素(flex container)的属性

css-container
  • display display 属性用于定义一个容器为 flex 容器。默认情况下,flex 容器是块级元素,但也可以设置为行内元素。在容器上设置 display:flex 后,它的所有直接子元素都可以参与 flex 布局。

.container {
display: flex; /* 或 inline-flex */
}

  • flex-direction flex-direction用于指定 flex 容器的主轴方向。主轴方向定义了 flex 项目的排列方向。默认值是 row,表示主轴方向是水平方向,即从左到右。除此之外,还可以设置为 row-reverse、column、column-reverse 等。

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

flex-direction: row

01

02

03

your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
}

flex-direction: row-reverse

01

02

03

your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
flex-direction:row-reverse;
_10
}

flex-direction: column

01

02

03

your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
flex-direction:column;
_10
}

flex-direction: column-reverse

01

02

03

your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
flex-direction:column-reverse;
_10
}

  • flex-wrap flex-wrap 属性用于指定 flex 项目是否允许换行。默认情况下,所有项目会尽量放在一行上,当一行放不下时,它们会缩小以适应。但是,你可以通过设置 flex-wrap 属性,让项目可以换行。可选值包括 nowrap、wrap 和 wrap-reverse
    • nowrap(默认):所有的flex子元素都将在一行上展示。
    • wrap:flex子元素将会从上到下换行展示。
    • wrap-reverse:flex子元素将会从下到上换行展示。

.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}

flex-wrap: nowrap

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
}

flex-wrap: wrap

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
flex-wrap: wrap
_10
}

flex-wrap: wrap-reverse

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
flex-wrap: wrap-reverse
_10
}

  • flex-flow 属性,它是 flex-directionflex-wrap 两个属性的缩写,用于同时设置它们的值。默认值是 row nowrap,即主轴方向是水平方向,不允许换行。

  • justify-content 属性 justify-content 定义了沿着主轴线的对齐方式。当所有的 flex 子项都无法缩小或已达到最大宽度时,它有助于分配额外的自由空间。当子项溢出行时,它还能在某种程度上控制它们的对齐方式。容器的justify-content属性可以设置以下取值:

    • flex-start(默认值):子项向 flex-direction 的起始位置堆叠。
    • flex-end:子项向 flex-direction 的结束位置堆叠。
    • start:子项向书写方式的起始位置(the start of the writing-mode direction)堆叠。
    • end:子项向书写方式的结束位置(he end of the writing-mode direction)堆叠。
    • left:子项向容器的左边缘堆叠,除非这在 flex-direction 方向上不合理,那么它会表现得像 start 一样。
    • right:子项向容器的右边缘堆叠,除非这在 flex-direction 方向上不合理,那么它会表现得像 end 一样。
    • center:子项在行上居中对齐。
    • space-between:子项在行上均匀分布,第一个子项在起始线上,最后一个子项在结束线上。
    • space-around:子项在行上均匀分布,每个子项两侧的间隔相等。需要注意的是,虽然视觉上的空间不相等,但所有子项两侧的空间相等。第一个子项与容器边缘之间有一个单位的空间,但下一个子项之间的空间是两个单位,因为下一个子项有它自己的间隔。
    • space-evenly:子项在行上均匀分布,任何两个子项之间(以及边缘之间的空间)的间距都相等。

.container {
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly | start | end | left | right ... + safe | unsafe;
}

需要注意的是,这些取值的浏览器支持情况比较复杂。例如,某些版本的 Edge 不支持 space-between,Chrome 中也没有 start/end/left/right。MDN网站有详细的支持情况图表。最安全的取值是 flex-startflex-endcenter

justify-content: flex-start

01
02
03
04
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
justify-content: flex-start
_10
}

justify-content: flex-end

01
02
03
04
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
justify-content: flex-end
_10
}

justify-content: center

01
02
03
04
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
justify-content: center
_10
}

justify-content: space-between

01
02
03
04
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
justify-content: space-between
_10
}

justify-content: space-around

01
02
03
04
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
justify-content: space-around
_10
}

justify-content: space-evenly

01
02
03
04
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
justify-content: space-evenly
_10
}

  • align-items,这个属性决定了在交叉轴上,如何对齐子项。可以把它看做是与主轴垂直的justify-content属性。默认值为stretch,表示子项沿交叉轴拉伸以填充整个容器。 其他可能的值包括:
    • stentch : 默认值,表示子项沿交叉轴拉伸以填充整个容器。
    • flex-start / start / self-start:在交叉轴上的起始位置放置子项。可以理解为顶部对齐。
    • flex-end / end / self-end:在交叉轴上的结束位置放置子项。可以理解为底部对齐。
    • center:在交叉轴上居中放置伸缩项。垂直方向居中对齐。
    • baseline:按子项的baseline对齐。

.container {
align-items: stretch | flex-start | flex-end | center | baseline | first baseline | last baseline | start | end | self-start | self-end + ... safe | unsafe;
}

align-items: stretch

01
02
03
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-items: stretch
_10
}

align-items: flex-start

01
02
03
your.css
your.html
Copy

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

align-items: flex-end

01
02
03
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-items: flex-end
_10
}

align-items: center

01
02
03
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-items: center
_10
}

align-items: baseline

01
02
03
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-items: baseline
_10
}

  • align-content align-content是用于控制flex容器内多行子元素在交叉轴上的对齐方式,类似于justify-content控制主轴上的对齐方式。它可以让一组子元素聚集在顶部或底部,或者拉伸以填充空间,或者在行之间留有间距。

需要注意的是,该属性仅在多行flex容器中生效,即flex-wrap属性设置为wrap或wrap-reverse。单行flex容器(即flex-wrap属性设置为默认值no-wrap的情况)不会受到align-content的影响。

align-content属性的取值有:

  • normal(默认值):项目将按照默认位置排列,就好像没有设置该属性一样。
  • flex-start / start:所有子元素将排列在容器的开始位置。
  • flex-end / end:所有子元素将排列在容器的结束位置。flex-end更支持flex-direction,而end则支持writing-mode的方向。
  • center:所有子元素在容器中垂直居中对齐。
  • space-between:所有子元素平均分布;第一行在容器的开始位置,最后一行在容器的结束位置。
  • space-around:所有子元素均匀分布,每行周围有相同的空间。
  • space-evenly:所有子元素均匀分布,每行之间有相等的空间。
  • stretch:每一行子元素都将拉伸以占用交叉轴方向的剩余空间。

align-content: normal

01
02
03
04
05
06
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: normal
_10
}

align-content: flex-start

01
02
03
04
05
06
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: flex-start
_10
}

align-content: flex-end

01
02
03
04
05
06
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: flex-end
_10
}

align-content: center

01
02
03
04
05
06
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: center
_10
}

align-content: space-between

01
02
03
04
05
06
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: space-between
_10
}

align-content: space-evenly

01
02
03
04
05
06
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: space-evenly
_10
}

align-content: space-around

01
02
03
04
05
06
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: space-around
_10
}

align-content: stretch

01
02
03
04
05
06
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: stretch
_10
}

  • gap, row-gap, column-gap 这几个gap相关的属性,用于控制flex items之间的间距。它仅适用于非外边缘的子元素之间的间距。 这个属性可以通过指定一个或两个值来设置,第一个值表示行间距,第二个值表示列间距,如果只指定一个值,则它将应用于行和列的间距。 该属性的行间距和列间距也可以分别使用row-gap和column-gap属性单独设置。

此外,该属性被认为是一个最小的间隙,如果因为某些原因(例如justify-content: space-between)间隔变大,则间隔将仅在该空间变小时生效。 此属性不仅适用于flexbox,还适用于grid and multi-column 布局。


.container {
display: flex;
...
gap: 10px;
gap: 10px 20px; /* row-gap column gap */
row-gap: 10px;
column-gap: 20px;
}

子元素(flex items)的属性

css-items
  • order,默认情况下,Flex 容器中的子元素是按照它们在源代码中出现的顺序进行布局的。但是,可以使用 order 属性来控制它们在容器中出现的顺序。通过在子元素上设置 order 属性,可以将某个子元素移动到其子元素的前面或后面。

在下面的示例中,.item 类选择器表示将 order 属性应用于具有 .item 类的 Flex 子元素。order 属性的默认值是 0,但是可以将其设置为任何数字值,以使项目出现在其他项目之前或之后。值越大,项目在 Flex 容器中出现的位置就越靠后。

此外,如果两个或多个项目具有相同的 order 值,则它们将按照它们在源代码中的出现顺序进行布局。也就是说,如果两个项目的 order 属性都设置为 1,则它们仍然会按照它们在源代码中的顺序进行布局。

01
02
03
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: stretch
_10
}
_10
_10
.item {
_10
order: 5; /* default is 0 */
_10
}

  • flex-grow,它定义了flex 子元素在需要时如何进行扩展。这个属性接受一个无单位的值,该值作为一个比例。它决定了子元素应该占据flex容器可用空间的多少。

如果所有子元素的flex-grow属性都设置为1,那么容器中剩余的空间将被平均分配给所有子元素。如果其中一个子元素的值为2,那么这个子元素占用的空间将是其他子元素中任何一个的两倍。


.item {
flex-grow: 1; /* default 0 */
}

01
02
03
01
02
03
your.css
flex-grow-0.html
flex-grow-1.html
Copy

_10
.flex-container {
_10
display: flex;
_10
align-content: stretch
_10
}
_10
_10
.item {
_10
flex-grow: 1; /* default 0 */
_10
}

  • flex-basis 属性定义了元素在剩余空间分配之前的默认大小。它可以是一个长度值(例如 20%、5rem 等)。

.item {
flex-basis: | auto; /* default auto */
}

01
02
03
your.css
your.html
Copy

_10
.flex-container {
_10
display: flex;
_10
}

原文可以戳这里