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 */
}
Copy
  • flex-direction flex-direction用于指定 flex 容器的主轴方向。主轴方向定义了 flex 项目的排列方向。默认值是 row,表示主轴方向是水平方向,即从左到右。除此之外,还可以设置为 row-reverse、column、column-reverse 等。
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
Copy

flex-direction: row

01

02

03

your.css
your.html
Copy
.flex-container {
display: flex;
}

flex-direction: row-reverse

01

02

03

your.css
your.html
Copy
.flex-container {
display: flex;
flex-direction:row-reverse;
}

flex-direction: column

01

02

03

your.css
your.html
Copy
.flex-container {
display: flex;
flex-direction:column;
}

flex-direction: column-reverse

01

02

03

your.css
your.html
Copy
.flex-container {
display: flex;
flex-direction:column-reverse;
}
  • 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;
}
Copy

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
.flex-container {
display: flex;
}

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
.flex-container {
display: flex;
flex-wrap: wrap
}

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
.flex-container {
display: flex;
flex-wrap: wrap-reverse
}
  • 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;
}
Copy

需要注意的是,这些取值的浏览器支持情况比较复杂。例如,某些版本的 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
.flex-container {
display: flex;
justify-content: flex-start
}

justify-content: flex-end

01
02
03
04
your.css
your.html
Copy
.flex-container {
display: flex;
justify-content: flex-end
}

justify-content: center

01
02
03
04
your.css
your.html
Copy
.flex-container {
display: flex;
justify-content: center
}

justify-content: space-between

01
02
03
04
your.css
your.html
Copy
.flex-container {
display: flex;
justify-content: space-between
}

justify-content: space-around

01
02
03
04
your.css
your.html
Copy
.flex-container {
display: flex;
justify-content: space-around
}

justify-content: space-evenly

01
02
03
04
your.css
your.html
Copy
.flex-container {
display: flex;
justify-content: space-evenly
}
  • 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;
}
Copy

align-items: stretch

01
02
03
your.css
your.html
Copy
.flex-container {
display: flex;
align-items: stretch
}

align-items: flex-start

01
02
03
your.css
your.html
Copy
.flex-container {
display: flex;
align-items: flex-start
}

align-items: flex-end

01
02
03
your.css
your.html
Copy
.flex-container {
display: flex;
align-items: flex-end
}

align-items: center

01
02
03
your.css
your.html
Copy
.flex-container {
display: flex;
align-items: center
}

align-items: baseline

01
02
03
your.css
your.html
Copy
.flex-container {
display: flex;
align-items: baseline
}
  • 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
.flex-container {
display: flex;
align-content: normal
}

align-content: flex-start

01
02
03
04
05
06
your.css
your.html
Copy
.flex-container {
display: flex;
align-content: flex-start
}

align-content: flex-end

01
02
03
04
05
06
your.css
your.html
Copy
.flex-container {
display: flex;
align-content: flex-end
}

align-content: center

01
02
03
04
05
06
your.css
your.html
Copy
.flex-container {
display: flex;
align-content: center
}

align-content: space-between

01
02
03
04
05
06
your.css
your.html
Copy
.flex-container {
display: flex;
align-content: space-between
}

align-content: space-evenly

01
02
03
04
05
06
your.css
your.html
Copy
.flex-container {
display: flex;
align-content: space-evenly
}

align-content: space-around

01
02
03
04
05
06
your.css
your.html
Copy
.flex-container {
display: flex;
align-content: space-around
}

align-content: stretch

01
02
03
04
05
06
your.css
your.html
Copy
.flex-container {
display: flex;
align-content: stretch
}
  • 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;
}
Copy

子元素(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
.flex-container {
display: flex;
align-content: stretch
}

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

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

.item {
flex-grow: 1; /* default 0 */
}
Copy
01
02
03
01
02
03
your.css
flex-grow-0.html
flex-grow-1.html
Copy
.flex-container {
display: flex;
align-content: stretch
}

.item {
flex-grow: 1; /* default 0 */
}
  • flex-basis 属性定义了元素在剩余空间分配之前的默认大小。它可以是一个长度值(例如 20%、5rem 等)。
.item {
flex-basis: | auto; /* default auto */
}
Copy
01
02
03
your.css
your.html
Copy
.flex-container {
display: flex;
}

原文可以戳这里