# Flex 布局(上)
# 1. 前言/历史
网页布局(layout)是 CSS 的一个重点应用。布局最核心的问题是:如何在一行中显示两个 block 元素?
从历史发展的时间顺序来看,解决这个问题的方案有三种:
使用 <table> 元素布局;
使用 position:static + float 布局;
使用 position:relative + position:absolute 布局。
提示
语义化是 HTML5 的一个重点,例如它提出 <strong>
来替代 <b>
。对于常用于布局的无语义的 <div>
元素,HTML5 也提出了几个替代它的语义化元素。
历史上,在经历了上述三种方案的发展之后,W3C 组织最终提出了一个统一的标准的解决方案:Flex 布局。
# 2. Flex 布局是什么?
Flex 是 Flexible Box 的缩写,意为 “弹性布局” ,用来为盒状模型提供最大的灵活性。
任何一个容器都可以指定为 Flex 布局。
.box {
display: flex;
}
行内元素也可以使用 Flex 布局。
.box {
display: inline-flex;
}
flex 和 inline-flex 的区别在于,上述例子中的 flex 类型的 .box 是独占一行,而 inline-flex 的 .box 不要求独占一行。
注意
父元素设置为: display: flex
以后,其子元素的 float
、clear
和 vertical-align
属性将失效。
# 3. 基本概念
采用 flex 布局的元素,称为 flex 容器(flex container),简称『容器』。它的所有子元素自动成为容器成员,称为 flex 项目(flex item),简称『项目』。
一个 flex 容器中默认存在两根轴:主轴(main axis)和交叉轴(cross axis)。主轴和交叉轴成 90° 垂直交叉,这也是为什么第二根轴被称为『交叉』轴的原因。
默认情况下,主轴是水平的,方向是从左往右,那么交叉轴自然就是垂直的。毫无疑问,主轴是水平还是垂直,以及它的方向,都是 可以设置 的 。
注意
主轴的相关属性会影响到交叉轴,但是反之,交叉轴影响不到主轴。
无论水平还是垂直,主轴的开始位置(与边框的交叉点)被称作 主轴的起点(main start)。与之对应的,结束的位置被称作 主轴的终点(main end)。同样,交叉轴也有起点和终点的概念。
主轴水平时:
- 如果方向是从左往右,那么,毫无疑问,主轴的起点在左边线,终点在右边线。
- 如果方向是从右往左,那么,毫无疑问,主轴的起点在右边线,终点在左边线。
- 主轴水平,那么交叉轴必然是垂直。此时,无论主轴是从左往右,还是从右往左,交叉轴的方向都是从上往下 。所以,交叉轴的起点在上边线,终点在下边线。
主轴垂直时:
- 如果方向是从上往下,那么,毫无疑问,主轴的起点在上边线,终点在下边线。
- 如果方向是从下往上,那么,毫无疑问,主轴的起点在下边线,终点在上边线。
- 主轴垂直,那么交叉轴必然是水平。此时,无论主轴是从上往下,还是从下往上,交叉轴的方向都是从左往右。那么,毫无疑问,交叉轴的起点在左边线,终点在右边线。
flex 容器的核心属性常见有以下 4 个:
- flex-direction
- flex-wrap
- justify-content
- align-items
注意
这 4 个属性都是设置在容器元素上的。
# 4. 核心属性:flex-direction
.box {
flex-direction: row | row-reverse | column | column-reverse;
}
默认值为 row 。
flex-direction 属性控制着主轴的水平/垂直,以及方向。
flex-direction: row
主轴水平,方向是从左往右。主轴起点在左,终点在右。
此时,交叉轴自然就是垂直,方向是从上往下。
flex-direction: row-reverse
主轴水平,方向是从右往左。主轴起点在右,终点在左。
此时,交叉轴自然就是垂直,方向仍然是从上往下。
flex-direction: column
主轴垂直,方向是从上往下。主轴起点在上,终点在下。
此时,交叉轴自然就是水平,方向是从左往右。
flex-direction: column-reverse
主轴垂直,方向是从下往上。主轴起点在下,终点在上。
此时,交叉轴自然就是水平,方向仍然是从左往右。
# 5. 核心属性:flex-wrap
默认情况下,flex 元素的子元素(item)都『串』在主轴上(无论主轴是水平还是垂直)。
.box {
flex-wrap: nowrap | wrap | wrap-reverse;
}
flex-wrap 属性定义,如果一条轴线排不下,如何换行。
默认值为 nowrap
。
flex-wrap: nowrap
nowrap 表示不换行,即,flex 元素的所有子元素,都要在同一行。
flex-wrap: wrap
表示换行,换行的方向是沿交叉轴方向换行。形如:
flex-direction: row | row-reverse
时,由于交叉轴的方向是从上往下的。因此,换行时,第二行就在第一行的『下』面。flex-direction: column | column-reverse
时,由于交叉轴方向是从左往右。因此,换行时,第二行就在第一行的『右』边。
flex-wrap: wrap-reverse
表示逆向换行,换上的方向是『逆』交叉轴方向。形如:
由于这里交叉轴的方向是从上往下,因此,逆向换行时,第二行就在第一行的『上』面。
# 6. 二合一属性:flex-flow 属性
flex-flow 属性不是『新』属性,它是 flex-direction + flex-wrap 属性的组合加简写形式。默认值为 row nowrap
。
.box {
flex-flow: <flex-direction> || <flex-wrap>;
}
# 7. 核心属性:justify-content
.box {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
justify-content 属性定义了项目在『主轴』上的对齐方式。
# | 说明 |
---|---|
flex-start | 默认值,所有 item 整体都靠近主轴的起点位置 |
flex-end | 所有 item 整体靠近主轴的终点位置 |
center | 所有 item 整体居中,主轴的起点和终点有留白 |
space-between | 起点-终点两端对齐, 子元素间均分空白,边线处无间距。 |
space-around | 和 space-between 类似。 不过起点-终点和边框间有间距。 这个间距等于 1/2 的子元素间的间距。 |
注意
这里是以 flex-direction: row
为样本进行的举例。当 flex-direction
属性值为其它值时,相关概念是一样的。
# 8. 核心属性:align-items
.box {
align-items: flex-start | flex-end | center | baseline | stretch;
}
align-items 属性定义 flex 元素的子元素(item)在交叉轴上如何对齐。
它可能取 5 个值。
# | 说明 |
---|---|
flex-start | 所有子元素都对齐交叉轴的起点。 |
flex-end | 所有子元素都对齐交叉轴的终点。 |
center | 所有子元素都对齐交叉轴中点。 |
baseline | 以所有子元素的第一行文字的基线对齐。 |
stretch | 默认值。 如果子元素自身未设置高度或设为 auto,那么子元素将被拉伸,以便同时对齐交叉轴的起点和终点。 |
注意
这里是以 flex-direction: row
为样本进行的举例。当 flex-direction
属性值为其它值时,相关概念是一样的。
# 9. align-content 属性
align-content 属性和 flex-wrap 属性有点关系。当 flex-wrap: wrap
和 flex-wrap:wrap-reverse
时,如果 Flex 元素的子元素(item)多到一行/一列放不下时,会出现折行的情况。这时,逻辑上就相当于有了多根平行的主轴。
align-content 属性就是用来设置这多根平行的主轴在交叉轴方向上的对齐方式。
.box {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
注意
如果项目只有一根轴线,该属性不起作用。
align-content: flex-start
多根轴线整体靠近主轴的起点:
如上例,三根主轴轴线紧靠在一起,整体对齐交叉轴的起点位置。
align-content: flex-end
多根轴线整体靠近主轴的终点:
如上例,三根主轴轴线紧靠在一起,整体对齐交叉轴的终点位置。
align-content: flex-center
多根轴线整体在主轴上居中:
如上例,三根主轴轴线紧靠在一起,在交叉轴方上居中,即交叉轴的起点和终点位置时留白。
align-content: space-between
多根轴线之间有间距,且最两端的轴线紧挨边线。
如上例,三根主轴轴线之间有等宽的间隔,同时,第一根轴对齐交叉轴的起点,最后一根轴对齐交叉轴的终点。
上面这个图例优点小瑕疵,『对齐』表现得不明显。
align-content: space-around
多根轴线之间有间距,但最两端的轴线和边线有间距。
如上例,三根主轴轴线之间有等宽的间隔,同时,第一根轴和交叉轴的起点有间隔,最后一根轴和交叉轴的终点有间隔,这个『间隔』等于轴与轴之间的间距的 1/2 。
align-content: stretch
这是默认值。每根主轴上的元素(item)会被拉伸,逻辑上,各个主轴一起均分交叉轴方向上的空间。前提是主轴上的元素没有指定明确的长度,或者为 auto 。
不过,各个主轴之间也有间隙,整体呈
主轴-间隙-主轴-间隙-...
的形式。因此,第一根主轴是对齐交叉轴起点位置,而最后一根轴和交叉轴终点位置之间有间隙。
← CSS 选择器 Flex 布局(下) →