CSS弹性盒子(flexbox)实用指南
上一节:《CSS 浮动 及其应用 》 | 下一节:《CSS网格布局(grid)实用指南 》
jcLee95
已入驻阿里云博客
邮箱 :291148484@163.com
本文地址:
- https://developer.aliyun.com/article/
- https://blog.csdn.net/qq_28550263/article/details/128431456
目 录
- 1. 图示:
flex-direction: row
; - 2. 图示:
flex-direction: row-reverse;
- 3. 图示:flex-direction: column;
- 4. 图示:flex-direction: column-reverse;
1. 概述
1.1 弹性盒子布局的概念
弹性盒子(flexbox) 是一种一维的布局模型,它给其 弹性项 之间提供了强大的空间分布和对齐能力。
flexbox 与 grid 布局的对比:
- flexbox 是一位布局:一次只能处理一个维度上的 弹性项 布局;
- grid 是二维布局:可以同时处理行和列上的布局。
1.2 如何创建弹性盒子
通过指定 display
属性值为 flex
或 inline-flex
可以创建弹性盒子,被指定该属性值的DOM元素称 弹性容器。弹性容器 的 In-flow子容器
称为 弹性项,弹性项使用 弹性布局模型 进行布局。
后文中,弹性容器 即弹性盒子父元素,弹性项 即 弹性盒子的弹性子元素。
例如这是我们在 图示:flex-direction: row
; 小节中使用过的代码:
<ul class="flex-box"> <li>element-1</li> <li>element-2</li> <li>element-3</li> </ul> <style type="text/css"> ul.flex-box { display: flex; flex-direction: row; justify-content: space-between; background-color: beige; } ul.flex-box li { list-style: none; width: 100px; height: 50px; background-color: cadetblue; border: 2px solid #000000; } </style>
你不一定将 ul
-li
元素指定为弹性盒子父 弹性项,普通的div
等其它 html 元素都可以。
2. 弹性项 排列方向控制
2.1 flex 的轴线
2.1.1 主轴 和 交叉轴 的概念
flex 的轴线包括 主轴 和 交叉轴。交叉轴是 垂直于主轴 方向上的轴。
注意:MDN 中文文档的一处错误:
MDN 中文翻译上将 主轴 注释为 横轴,将 纵轴 注释为 纵轴 其实是不准确的:
英文原版似乎也找不到这样的注释:
中文文档是 github 上由网友翻译的。之所以导致这样地错误,是因为翻译的网友可能用了机器翻,未认真阅读。上文中还有一处显著的翻译错误:
此处的原文是:
其意思是:
我们使用justify-content 在 主轴上 对齐项目,在本例中,主轴是水平运行的内联轴。并不是说主轴是水平方向的。这个文档翻译导致部分读者在未确定主轴方向时直接认为主轴就是横轴。
另外,在 W3C官方的 CSS 文档 中,对主轴方向和交叉轴方向是这样定义的:
- 【main dimension】:The main axis of a flex container is the primary axis along which flex items are laid out. It extends in the main dimension.(flex容器的主轴是flex项目布局的主轴。它在主维度上延伸。)
- 【cross dimension】:The axis perpendicular to the main axis is called the cross axis. It extends in the cross dimension.(垂直于主轴的轴称为交叉轴[也可译为垂直轴]。它在垂直方向上延伸。)
并且其给出的案例图示注明了是一个 行弹性容器 下的术语:
MDN 中文翻译者将这些忽略了,简单地认为主轴就是横轴,这是错误的。关于这一点,在阅读后文属性的使用时也会由体现。
之所以花比较大的篇幅说明是,很多网络文章、视频都跟着犯了这个错误。因此建议减少对中文翻译的依赖,有条件尽量阅读英语原文。
虽然默认值情况下如此,但事实上 主轴既可以是横轴,也可以是纵轴,取决于你将主轴方向相对于inline axis
的定义。
下一小节我们介绍如何使用 flex-direction
属性用于指定主轴方向,它也称 弹性方向。一旦主轴方向指定了,那么与之对应的交叉轴方向也就确定了。
在后续小节讲解的对齐方式相关属性中,如 justify-content
、aline-items
,它们分别用于弹性盒子 弹性项沿主轴方向对齐 以及 沿交叉轴方向对齐 。如果你错误地确定了主轴,将无法
行轴(inline axis
)和 行方向(inline dimension
)的概念
W3C 文档:https://www.w3.org/TR/css-writing-modes-4/#inline-axis
主轴方向 是相对于 行轴(inline axis
)方向(简称行方向)而言的(见2.1.2 控制主轴方向 flex-direction
属性小节)。因此有必要先捋一捋什么是 行轴。
概念 | 描述 | 中文 | 说明 |
行方向 ( inline dimension ) |
The dimension parallel to the flow of text within a line, i.e. the horizontal dimension in horizontal writing modes, and the vertical dimension in vertical writing modes. | 平行于一行内文本流向的尺寸,即 水平书写模式 下的 水平方向 和 垂直书写模式 下的 垂直方向。 | 多数情况下是水平书写模式,本文后续小节介绍各种属性用法时假定是在水平书写模式下进行的,对应inline axis 的方向为水平方向,则flex-direction 为row 时对应与横轴。后文中不再说明。 |
行轴 ( inline axis ) |
The axis in the inline dimension, i.e. the horizontal axis in horizontal writing modes and the vertical axis in vertical writing modes. | 行维度中的轴,即水平书写模式中的水平轴 和 垂直书写模式 中的 垂直轴。 |
块轴(block axis
)和 块方向(block dimension
)的概念
W3C 文档:https://www.w3.org/TR/css-writing-modes-4/#block-axis
概念 | 描述 | 中文 | 说明 |
块方向 ( block dimension ) |
The dimension perpendicular to the flow of text within a line, i.e. the vertical dimension in horizontal writing modes, and the horizontal dimension in vertical writing modes. | 平行于一行内文本流向的尺寸,即 水平书写模式 下的 垂直方向 和 垂直书写模式 下的 水平方向。 | 块方向(或译为块维度),与行方向(inline dimension )垂直。 |
块轴 ( block axis ) |
The axis in the block dimension, i.e. the vertical axis in horizontal writing modes and the horizontal axis in vertical writing modes. | 行维度中的轴,即水平书写模式中的垂直轴 和 垂直书写模式 中的 水平轴。 |
2.1.2 控制主轴方向 flex-direction
属性
主轴 使用 水平方向 还是 竖直方向 作为 弹性方向 属性 flex-direction
定义,它可以取 4 个值:
flex-direction 属性值 |
主轴方向 | 说明 |
row | 与当前书写模式的inline axis 方向相同。main-start 和main-end 方向分别等效于当前写入模式的行内开始和行内结束方向。 |
水平书写模式下的 水平方向 |
row-reverse | 与 row 相同,只是 main-start 和 main-end 方向互换了。 |
水平书写模式下的水平方向,弹性项逆序排列 |
column | flex容器的主轴与当前书写模式的 block axis 方向相同。main-start 和 main-end 方向分别相当于 当前写入模式 的块开始和块结束方向。 |
水平书写模式下的竖直方向 |
column-reverse | 与 column 相同,只是 main-start 和 main-end 方向互换了。 |
水平书写模式下的竖直方向,弹性项逆序排列 |
1. 图示:flex-direction: row
;
2. 图示:flex-direction: row-reverse;
3. 图示:flex-direction: column;
4. 图示:flex-direction: column-reverse;
2.2 小结
flex-direction 属性用于选择主轴方向:
- 如果
flex-direction
属性的值是 row 或者 row-reverse,则主轴为横(水平)轴,交叉轴为纵(竖直)轴; - 如果
flex-direction
属性的值是 column 或者 column-reverse,则主轴为纵(竖直)轴,交叉轴为横(水平)轴; - 如果属性值带 -reverse 后缀,则表示flex 弹性项 逆序排列,否则正序排列。
3. 弹性项 对齐、间距和换行控制
3.1 Flex 对齐方式
3.1.1 概述
弹性盒子中,可以通过 justify-content
、align-items
、align-self
、align-content
四个属性控制盒子中的 弹性项 在 主轴 和 交叉轴 上的对齐方式:
属性 | 描述 |
justify-content |
控制 主轴上 所有 flex 弹性项 的对齐 |
align-items |
控制 交叉轴 上 所有 flex 弹性项 的对齐 |
align-self |
控制 交叉轴 上 单个 flex 弹性项的对齐 |
align-content |
控制 多条主轴 的 flex 弹性项 在 交叉轴 的对齐 |
3.1.2 控制主轴对齐的 justify-content
属性
justify-content
属性用于控制 主轴上 所有 flex 弹性项 的对齐。
举个例子:
<ul class="flex-box"> <li>element-1</div> <li>element-2</div> <li>element-3</div> </ul> <style type="text/css"> * { border: 0; padding: 0; } ul.flex-box { display: flex; background-color: beige; height: 180px; } ul.flex-box li { list-style: none; width: 100px; height: 50px; background-color: cadetblue; border: 1px solid #000000; } </style>
1. 当 flex-direction: row;
时
此时justify-content 控制的方向为 水平方向(横向)。
(1)flex-start
justify-content: flex-start;
时,弹性项紧凑地从起始向结束方向(从左向右)排列:
(2)flex-end
justify-content: flex-end;
时,弹性项 从结束向起始方向(从右向左)排列:
(3)center
justify-content: center;
时,弹性项 (横向)居中排列:
(4)space-around
justify-content: space-around;
时,均匀排列每个弹性项,使每个弹性项周围分配相同的空间:
(5)space-between
justify-content: space-between;
时,均匀排列每个弹性项,使首个弹性项放置于起点,末尾弹性项放置于终点:
(6)space-evenly
justify-content: space-evenly;
时,均匀排列每个弹性项,使每个弹性项之间的间隔相等:
2. 当 flex-direction: column;
时
此时justify-content 控制的方向为 竖直方向(纵向)。
(1)flex-start
justify-content: flex-start;
时,弹性项 紧凑地从起始向结束方向(从上向下)排列:
(2)flex-end
justify-content: flex-end;
时,弹性项 紧凑地从结束向起始方向(从下向上)排列:
(3)center
(4)space-around
justify-content: space-around;
时,均匀排列每个弹性项,使每个 弹性项 周围分配相同的空间:
(5)space-between
justify-content: space-between;
时,均匀排列每个弹性项,使首个弹性项放置于起点,末尾弹性项放置于终点:
(6)space-evenly
justify-content: space-evenly;
时,均匀排列每个弹性项,使每个 弹性项 之间的间隔相等:
3.1.3 控制交叉轴对齐的 aline-items
属性
aline-items
属性用于控制 交叉轴 上的对齐方式,它所控制的反向永远是 与 justify-content
控制的方向(主轴对齐方向)是垂直的, 也就是说:
- 如果主轴为水平方向(
row
或者row-reverse
),则aline-items
属性控制的是 竖直方向上的对齐方式; - 如果主轴为竖直方向(
column
或者column-reverse
),则aline-items
属性控制的是 水平方向上的对齐方式;
1. 当 flex-direction: row;
时
此时aline-items 控制的方向为 竖直方向(纵向)。
(1)start
弹性项 会在 适当的轴上(此时为纵轴) 朝向对齐容器的起始边缘彼此齐平地打包。
(2)flex-start
弹性项 向 交叉轴 起点对齐。
(3)end
弹性项 在适当的轴上(此时为纵轴) 朝向对齐容器的末端边缘彼此齐平地打包。
(4)flex-end
弹性项 向 交叉轴(这时是纵轴) 终点对齐。
(5)center
弹性项 在 交叉轴居中(这时是纵轴)。如果 弹性项 在 交叉轴 上的高度高于其容器,那么在两个方向上溢出距离相同。
(6)left
这些 弹性项 朝向对齐容器的左边缘彼此齐平地打包。如果属性的轴与行轴不平行,则该值的行为类似于 start
。
(7)right
这些 弹性项 在适当的轴上朝着对齐容器的右边缘彼此齐平地打包。如果属性的轴与行轴不平行,则该值的行为类似于 start
。
(8)stretch
弹性项 含外边距的 交叉轴(这时是纵轴) 尺寸被拉升至行高。
(9)safe
与 alignment
关键字一起使用。如果选择的关键字意味着项目溢出对齐容器而导致数据丢失,则项目将改为对齐,就像对齐模式是 start
一样。
(10)unsafe
与 alignment
关键字一起使用。不管项目和对齐容器的相对大小如何,也不管是否会发生导致数据丢失的溢出,都会遵循给定的对齐值。
2. 当 flex-direction: column;
时
此时aline-items 控制的方向为 水平方向(横向)。
(1)start
弹性项 会在 适当的轴上(此时为横轴) 朝向对齐容器的起始边缘彼此齐平地打包。
(2)flex-start
弹性项 向 交叉轴 (此时为横轴)起点对齐。
(3)end
弹性项 在适当的轴上(此时为横轴) 朝向对齐容器的末端边缘彼此齐平地打包。
(4)flex-end
弹性项 向 交叉轴(这时是横轴) 终点对齐。
(5)center
弹性项 在 交叉轴居中(这时是横轴)。如果 弹性项 在 交叉轴 上的高度高于其容器,那么在两个方向上溢出距离相同。
(6)left
这些 弹性项 朝向对齐容器的左边缘彼此齐平地打包。如果属性的轴与行轴(inline axis)不平行,则该值的行为类似于 start
。
(7)right
这些 弹性项 在适当的轴上朝着对齐容器的右边缘彼此齐平地打包。如果属性的轴与行轴(inline axis)不平行,则该值的行为类似于 start
。
(8)stretch
弹性项 含外边距的 交叉轴(这时是横轴) 尺寸被拉升至行高。
(9)safe
与 alignment
关键字一起使用。如果选择的关键字意味着项目溢出对齐容器而导致数据丢失,则项目将改为对齐,就像对齐模式是 start
一样。
(10)unsafe
与 alignment
关键字一起使用。不管项目和对齐容器的相对大小如何,也不管是否会发生导致数据丢失的溢出,都会遵循给定的对齐值。
3.1.4 控制交叉轴 单个 弹性项 对齐的 align-self
属性
3.1.5 多条主轴 弹性项 在 交叉轴 的对齐 align-content
属性
3.2 Flex 换行:flex-wrap
属性
3.2.1 flex-wrap: wrap;
在flex父容器中使用 flex-wrap
属性可以用来控制 flexbox 的弹性项是否在必要的时候换行。比如我们拖动一个父容器设置 flex-wrap: wrap;
的弹性盒子,手动拖动改变浏览器页面大小,可以看到弹性项在 弹性容器 大小不够的时候逐个自动换行,就像依次 “流动” 到前一个 弹性项 的下方:
3.2.2 flex-wrap: nowrap;
如果你不希望弹性项自动换行,则可以在弹性父容器中将flex-wrap
属性值指定为nowrap
。这样,即使 弹性容器 大小不够 弹性项 在弹性方向大小也不会发生换行,比如:
4. 弹性项大小(比例)的控制
4.1 概述
本节我们介绍三个用于控制弹性项的尺寸和伸缩性的属性,他们分别是 flex-grow
, flex-shrink
, 和 flex-basis
。其中:
属性 | 用途 |
flex-basis |
在该 弹性项 未 伸张 和 收缩 之前,它的大小是多少 |
flex-grow |
该弹性项得到(伸张)多少 正自由空间 |
flex-shrink |
从该弹性项要消除(收缩)多少 负自由空间 |
自由空间 讨论的是 空间剩余 和 空间不足 的问题。弹性容器 和 弹性项 都有其自身的尺寸大小,因此 弹性项 的尺寸之和 即可能 大于 也可能 小于flexbox的尺寸。
- 当 弹性项 尺寸之和 < 弹性容器时,弹性容器 有多余的空间没有被填充。
这个多出来的空间就被称为该 弹性容器 的 正自由空间; - 当 弹性项 尺寸之和 > 弹性容器 时,弹性容器 没有足够的空间容纳所有Flex项目。
这时所缺少的空间就被称做该 弹性容器 的 负自由空间。
4.2 flex-basis 属性
flex-basis
属性表示弹性项未伸张和收缩之前的大小。
4.3 flex-grow 属性
flex-grow
设置与 flex 弹性项 中,用于指定 flex 增长值。这决定了当 正自由空间 分配时,flex 弹性项相对于 flex 容器 中的其余 flex 弹性项的增长程度:
- 如果你所有的 flex弹性项 设置了 相同的flex-grow属性值,那么空间将会在 flex 弹性项 之间平均分配。
- 如果 flex-grow 的值全部相同,并且在 flex 容器 中还有 正自由空间 , 那么正自由空间就会平均的分配给所有的 flex 弹性项。
4.4 flex-shrink 属性
浏览器计算 flex 弹性项的 flex-basis
时,只要 flex-shrink
有正值则 flex 弹性项就会收缩以至于它们不会溢出 flex 容器。
因此:
flex-grow
用于添加可用空间;flex-shrink
用于减少空间来使盒子适应它们的容器而不溢出。
4.5 应用:如何占满弹性盒子的剩余空间
待编写
5. 绝对定位的弹性项
待编写
6. 折叠的弹性项
待编写
7. 在 flexbox 中使用 gap
属性
待编写
附录:相关知识补充
F1. CSS 中的对齐术语
F1.1 对齐项目(alignment subject)
对齐项目 是由 属性 对齐的 一个或多个 事物。
- 对于**
justify-self
** 和align-self
的 对齐项目, 是设置了该属性的框的边距框,并采用该框的书写模式。 - 对于
justify-content
和align-content
的 对齐项目, 由 布局模式 定义,并引用其内容的某个方面;它还假定设置了该属性的框的写入模式。
F1.2 对齐容器(alignment container)
对齐容器 是 对齐项目 在其中对齐的 矩形。它由 布局模式 所定义,但通常是 对齐项目 的包含块,并采用建立包含块的框的书写模式。
F1.3 回退对齐(fallback alignment)
一些排列只能在某些情况下实现,或者在它们能消耗多少空间方面受到限制。
例如,只有当有多个 对齐项目 时,space-between
才能运行,而基线对齐一旦完成,可能 不足以 吸收所有 多余的空间。在这些情况下,回退对齐(fallback alignment) 生效(如下所述)以完全消耗多余的空间。
F2. 对齐方式的类别及其特征
F2.1 位置对齐(positional alignment)
位置对齐 关键字包括:
center
,start
,end
,self-start
,self-end
,flex-start
,flex-end
,left
, 和right
位置对齐的关键字指定 对齐项目 相对于其 对齐容器(alignment container) 的位置。
关键字 | 描述 |
center (self, content) |
将 对齐项目 在其 对齐容器 内居中。 |
start (self, content) |
在适当的轴上,将 对齐项目 与 对齐容器 的起始边缘对齐。 |
end (self, content) |
在适当的轴上将 对齐项目 与 对齐容器 的末端边缘对齐。 |
self-start (self) |
对齐 对齐项目,使其与对齐容器的边缘齐平,对齐容器的边缘对应于 对齐项目 在相应轴上的起始侧。 |
self-end (self) |
对齐 对齐项目,使其与对齐容器的边缘齐平,该边缘对应于对齐对象在相应轴上的端侧。 |
flex-start (self, content) |
仅用于 弹性布局。[CSS-FLEXBOX-1] 对齐 对齐项目,使其与flex容器的主开始或交叉开始侧对应的对齐容器的边缘齐平,视情况而定。 在flex格式上下文之外使用时,该值的行为与start相同。也就是说,在不是flex项目的盒子上(或者假装是flex项目,例如当确定作为flex容器的子代的 绝对定位 (absolutely-positioned)盒子的静态位置时),当在 self-alignment 属性中使用时,该值表现为start,而在不是flex容器的盒子上,当在 content-distribution 属性中使用时,该值表现为start。 |
flex-end (self, content) |
仅用于 弹性布局。 根据需要,将 对齐项目 与对应于flex容器 主端(main-end ) 或 交叉端(cross-end)侧 的 对齐容器 的边缘对齐。 当在flex格式上下文之外使用时,该值表现为end。也就是说,在不是flex项目的盒子上(或者假装是flex项目,例如当确定作为flex容器子级的 绝对定位(absolutely-positioned) 盒子的静态位置时),该值在 self-alignment 属性中使用时表现为 end,而在不是flex容器的盒子上,该值在 content-distribution 属性中使用时表现为end。 |
left (only justify-*) |
将 对齐项目 与 对齐容器 的行左边缘或物理左边缘对齐,无论哪一个在适当的轴上。如果 属性的轴 不平行于任何一个 left↔right轴,则该值表现为start。目前,属性的轴 与 left↔right轴 不平行的唯一情况是在列flexbox中。 |
right (only justify-*) |
将 对齐项目 对齐,使其与 对齐容器 的右线边缘或物理右边缘(位于适当的轴上)齐平。 如果 属性的轴 不平行于任何一个 left↔right轴,则该值表现为 start。目前,属性的轴 与 left↔right轴 不平行的唯一情况是在 列 flexbox 中。 |
F2.2 基线对齐(Baseline Alignment)
基线对齐 关键字包括
baseline
和first
/last
基线对齐 是位置对齐的一种形式,它通过匹配对齐基线来对齐共享对齐上下文(如行中的单元格)中的多个对齐对象。如果基线共享组内的比对主体的位置没有完全受到基线比对的约束(即,它们可以在它们各自的比对容器内移动,同时保持基线比对),则它们尽可能后退比对,同时保持它们的基线比对。
基线对齐关键字用<baseline-position>
语法术语表示:
<baseline-position> = [ first | last ]? && baseline
第一个和最后一个值为框提供了基线对齐首选项:分别是 first
或 last
,默认为 first
。
- 当指定为
align-content
时,这些值触发基线内容对齐,在其内容框内移动框的内容,并且还可能影响框本身的大小。 - 当指定为
align-self
/justify-self
时,这些值触发基线自对齐,在其容器内移动整个框,这可能会影响其容器的大小。 - 当在盒子上指定基线
self-alignment
时,首先执行内容分布,然后得到的盒子及其内容是self-aligned
,然而,如果盒子在同一轴上也具有基线content-distribution
,或者如果它在同一轴上的content-distribution
属性是正常的,则它在该轴上使用的“内容分布”属性分别是其基线自对齐偏好first
或last
的基线对齐的开始或安全结束。 - 如果盒子不属于共享对齐上下文,则使用回退对齐。例如,块框上的“align-content: baseline”退回到开始对齐。后退对齐还用于在其对齐容器内对齐“基线共享”组。
F2.3 分布式对齐(Distributed Alignment)
分布式对齐 使用
stretch
,space-between
,space-around
, 和space-evenly
关键字描述。
justify-content
和 align-content
使用分布式对齐值 在 对齐项目 之间分配容器的额外空间。
当空间不能以这种方式分配时,这些值作为它们的后备对齐。每个分布值都有一个关联的默认回退对齐。(此模块的未来级别可能允许明确指定回退对齐。)
关键字 | 描述 | 说明 |
space-between |
对齐项目 均匀分布在 对齐容器 中。第一个对齐主题被放置为与对齐容器的起始边缘齐平,最后一个对齐主题被放置为与对齐容器的结束边缘齐平,其余的对齐主题被分布为任意两个相邻对齐主题之间的间距相同。 | 该值的默认 回退对齐 方式是 flex-start |
space-around |
对齐项目 均匀分布在 对齐容器 中,两端各有一半大小的空间。对齐对象的分布使得任意两个相邻对齐对象之间的间距相同,并且第一个对齐对象之前和最后一个对齐对象之后的间距是另一个间距的一半。 | 该值的默认 回退对齐 方式是 safe center |
space-evenly |
对齐项目 均匀分布在 对齐容器 中,两端留有全尺寸空间。分布对准对象,使得在第一个对准对象之前和最后一个对准对象之后的任意两个相邻对准对象之间的间距相同。 | 该值的默认 回退对齐 方式是 safe center |
stretch |
如果 对齐项目 的组合大小小于 对齐容器 的大小,则任何自动调整大小的对齐主题的大小相等地增加(不是成比例地),同时仍然遵守 max-height / max-width (或等效功能)所施加的约束,使得组合大小精确地填充对齐容器。 |
该值的默认 回退对齐 方式是 flex-start |
图: 分布式对齐(引用自 W3C)