Flexbox 布局系统
CSS 2.1 定义了 4 种布局模式:
- block layout,用于布局文档
- inline layout,用于布局文本
- table layout,用于以表格格式布局 2D 数据
- positioned layout,用于明确的定位,而不用考虑文档里的其他元素
现在 CSS 引入了新的布局模式,flex layout 和 grid layout,用来布局更复杂的应用和网页页面。
CSS Flexbox Layout Level 1
Flex layout 表面上看起来像 block layout,但是它没有像 float 和 clumns 这些在 block layout 中很重要的属性,取而代之的是它提供了更多简单有力的工具用于布局空间、对齐内容,这往往是很多 web apps 和 复杂网页所需要的。
Flex Layout 盒模型
弹性容器 包含着弹性项目的父元素。通过设置 display 属性的值为 flex 或 inline-flex 来定义弹性容器。容器内部子元素就被称为 弹性元素,这些 弹性元素 就以弹性布局模式进行布局 。
如果说传统的布局是基于块和内联的流动方向,那么 flex 布局就是基于弹性流动方向,下面这张来自 flex 规范的图解释了 flex 布局里的主要术语。
- main axis 主轴:
弹性元素默认沿着弹性容器的主轴进行排列。但是主轴不是一定为水平的,它是根据flex-direction的设置来决定的,示例图中的flex-direction设置为row。 - main-start | main-end:主轴开始的位置(与边框的交叉点)叫做
main-start,结束的位置叫做main-end。 - main size:
弹性容器占据的主轴尺寸叫做main size。 - cross axis 交叉轴: 垂直于主轴的轴被称为
交叉轴,因此它的方向取决于主轴的方向。 - cross-start | cross-end:交叉轴开始的位置(与边框的交叉点)叫做
cross-start,结束的位置叫做cross-end。 - cross size:单个
弹性元素占据的交叉轴尺寸叫做cross size。
弹性容器
| Name: | ‘display’ | |
|---|---|---|
| New values: | flex \ | inline-flex |
设置 display 值为 flex 或 inline-flex 会将元素定义为弹性容器,flex 使弹性容器称为块级元素,inline-flex 使容器成为单个不可分割的行内元素。
弹性容器 为它内容建立了一个弹性布局的上下文,将它的内部元素默认包裹成为 弹性元素。
弹性容器 不是 block 容器,因此有些为 block 容器 设计的属性不不适用,例如:
float和clear无法使弹性元素浮动或者清除浮动,也不会让它离开文本流。vertical-align对弹性元素是无效的。::first-line和::first-letter这类伪元素无法应用到弹性容器。
弹性元素
弹性盒子里的每个子元素会默认成为弹性元素,子元素内的连续序列文本块会被包裹在一个匿名的弹性元素块容器中,但是如果这个文本块只包含空格,那么它就不会被渲染(就好像这些 text nodes 被设置为 display:none 了一样)。
绝对定位的弹性容器子元素
绝对定位的子元素已经离开弹性流动布局,不再参与弹性容器内的弹性布局。
而这个绝对定位元素的静态位置,会被当做是弹性容器内唯一的弹性元素的位置来决定。由于绝对定位的元素是固定尺寸的,所以 stretch 值无法生效,会被默认成值 flex-start。
https://codepen.io/bubupu/pen/vJWrYP
弹性元素的 Margin 和 Padding
由于目前标准还未统一 弹性元素 的 margin 和 padding 的百分比的计算解决方式,因此要避免在 弹性元素 使用百分比 margin 和 padding
margin 值为 auto 将会自动扩大边距以吸收响应尺寸上的剩余空间,我们可以利用这个进行布局或者把相邻的元素推开。
折叠元素
指定 弹性元素 属性 visibility:collapse 会将 弹性元素 变成折叠的弹性元素,折叠的弹性元素 会从渲染中完全移除,但是会留下一个支撑来保障 cross-size 的稳定,不会引起整个页面结构的跳动。
https://codepen.io/bubupu/pen/qXVyVO
弹性容器属性
| Name: | 'flex-direction' | |||
|---|---|---|---|---|
| Value: | row \ | row-reverse \ | column \ | column-reverse |
| Initial: | row |
flex-direction 属性决定主轴的方向(即项目的排列方向)。
| Name: | 'flex-wrap' | ||
|---|---|---|---|
| Value: | nowrap \ | wrap \ | wrap-reverse |
| Initial: | nowrap |
flex-wrap 属性决定 弹性容器 在主轴排列不下的情况下是否要换行,以及新行堆叠的方向,即 交叉轴 的方向。
(1) nowrap

(2) wrap

(3) wrap-reverse

| Name: | 'flex-flow' | ||
|---|---|---|---|
| Value: | \ |
flex-flow 属性是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为 row nowrap
https://codepen.io/bubupu/pen/KvyxBd
flex-flow 的方向对 writing mode 敏感,例如有些中文文章是垂直布局的,这个时候一个 row 弹性容器实际流动方向是从上到下的,从右到左的。
| Name: | 'justify-content' | ||||
|---|---|---|---|---|---|
| Value: | flex-start \ | flex-end \ | center \ | space-between \ | space-around |
| Initial: | flex-start |
justify-content属性定义了项目在主轴上的对齐方式。
| Name: | 'align-items' | ||||
|---|---|---|---|---|---|
| Value: | flex-start \ | flex-end \ | center \ | baseline \ | stretch |
| Initial: | stretch |
align-items 属性定义项目在交叉轴上如何对齐。
如果项目未设置 cross size (高度或宽度) 或设为 auto,并且弹性元素在 交叉轴 方向上的 margin 不为 auto,stretch 就会占满交叉轴上的所有空间,但是其依然要被 min-height / min-width / max-height / max-width 所限制。
| Name: | 'align-content' | |||||
|---|---|---|---|---|---|---|
| Value: | flex-start \ | flex-end \ | center \ | space-between \ | space-around \ | stretch |
| Initial: | stretch |
align-content 属性定义了多行 弹性元素 的在 交叉轴 上对齐方式,类似于 justify-content,区别就是它是作用于交叉轴上的,当弹性元素只有一行时,则该属性不起作用。
弹性元素属性
| Name: | 'order' |
|---|---|
| Value: | |
| Initial: | 0 |
弹性元素 默认是以相同的优先级 0 进行排序,相同的优先级元素按照它们在文档流里的顺序进行排序,但是 order 属性能够改变 弹性元素 的顺序,order 属性值越小,顺序越优先。
.tabs {
display: flex;
}
.tabs > .current {
order: -1; /* Lower than the default of 0 */
}
order 改变顺序只是用于视觉上的渲染,而不能真正改变逻辑上的顺序。
| Name: | 'flex-grow' |
|---|---|
| Value: | |
| Initial: | 0 |
flex-grow 属性定义弹性元素的放大比例,默认为 0,即如果存在剩余空间,也不放大。如果设置所有的 弹性元素 的 flex-grow 属性为 1 , 那么所有弹性容器 空间就会被 弹性元素 以相同的大小占满。
| Name: | 'flex-shrink' |
|---|---|
| Value: | |
| Initial: | 1 |
flex-shrink 属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。如果所有项目的 flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的 flex-shrink 属性为0,其他项目都为1,则空间不足时,前者不缩小。

| Name: | 'flex-basis' | |
|---|---|---|
| Value: | content \ | <'width'> |
| Initial: | auto |
flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为 auto,即项目的本来大小。
| Name: | 'flex' | |||
|---|---|---|---|---|
| Value: | none \ | [<'flex-grow'><'flex-shrink'>?\ | \ | <'flex-basis'>] |
| Initial: | 0 1 auto |
flex 属性是 flex-grow,flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto。后两个属性可选。
该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
| Name: | 'align-self' | |||||
|---|---|---|---|---|---|---|
| Value: | auto \ | flex-start \ | flex-end \ | center \ | baseline \ | stretch |
| Initial: | auto |
align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的 align-items 属性,如果没有父元素,则等同于 stretch。