一、Flex布局是什么?
Flex
是Flexible Box
的缩写,翻译成中文就是“弹性盒子”,用来为盒装模型提供最大的灵活性。
给div这类块状元素元素设置display:flex
或者给span这类内联元素设置display:inline-flex
,flex布局即创建!其中,直接设置display:flex
或者display:inline-flex
的元素称为flex容器
,里面的子元素称为flex子项
。
在Flex布局中,所有相关属性正好分为两拨,一拨作用在flex容器上,还有一拨作用在flex子项上。具体参见下表:
作用在flex容器上 | 作用在flex子项上 |
---|---|
二、作用在flex容器上的CSS属性
1. flex-direction
flex-direction
用来控制flex子项整体布局方向,是从左往右还是从右往左,是从上往下还是从下往上。和CSS的direction属性相比就是多了个flex。
语法如下:
flex-direction: row | row-reverse | column | column-reverse;
其中:
row
:默认值,显示为行。方向为当前文档水平流方向,默认情况下是从左往右。如果当前水平文档流方向是rtl(如设置direction:rtl),则从右往左。row-reverse
:显示为行。但方向和row属性值是反的。column
:显示为列。column-reverse
:显示为列。但方向和column属性值是反的。
2. flex-wrap
flex-wrap
用来控制子项整体单行显示还是换行显示,如果换行,则下面一行是否反方向显示。这个属性比较好记忆,在CSS世界中,只要看到单词wrap一定是与换行显示相关
的,word-wrap
属性或者white-space:nowrap
或者pre-wrap
之类。
语法如下:
flex-wrap: nowrap | wrap | wrap-reverse;
其中:
- nowrap:默认值,表示单行显示,不换行。于是很容易出现宽度溢出的场景,其渲染表现比较复杂,需要对CSS3宽度有一定了解,可以阅读“理解CSS3 max/min-content及fit-content等width值”这篇文章。具体表现如下(以水平布局举例):
- flex子项最小内容宽度min-content之和大于flex容器宽度,则内容溢出,表现和white-space:nowrap类似。
- 如果flex子项最小内容宽度min-content之和小于flex容器宽度,则:
- flex子项默认的fit-content宽度之和大于flex容器宽度,则flex子项宽度收缩,正好填满flex容器,内容不溢出。
- flex子项默认的fit-content宽度之和小于flex容器宽度,则flex子项以fit-content宽度正常显示,内容不溢出。
在下面案例中,示意的图片默认有设置max-width:100%,flex子项div没有设置宽度,因此,flex子项最小宽度是无限小,表现为图片宽度收缩显示。如果我们取消max-width:100%样式,则此时flex子项最小宽度就是图片宽度,就可以看到图片溢出到了flex容器之外。
- wrap:宽度不足换行显示。
- wrap-reverse:宽度不足换行显示,但是是从下往上开始,也就是原本换行在下面的子项现在跑到上面。
3. flex-flow
flex-flow
属性是flex-direction
和flex-wrap
的缩写,表示flex布局的flow流动特性,
语法如下:
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
当多属性同时使用的时候,使用空格分隔。
显示效果戳这里
4. justify-content
justify-content
属性决定了水平方向子项的对齐和分布方式。CSS text-align
有个属性值为justify,可实现两端对齐,所以,当我们想要控制flex元素的水平对齐方式的时候,记住justify这个单词,justify-content属性也就记住了。
justify-content
可以看成是text-align
的远房亲戚,不过前者控制flex元素的水平对齐外加分布,后者控制内联元素的水平对齐。
语法如下:
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
其中:
flex-start
:默认值。逻辑CSS属性值,与文档流方向相关。默认表现为左对齐。flex-end
:逻辑CSS属性值,与文档流方向相关。默认表现为右对齐。center
:表现为居中对齐。space-between
:表现为两端对齐。between是中间的意思,意思是多余的空白间距只在元素中间区域分配。使用抽象图形示意如下:
space-around
: around是环绕的意思,意思是每个flex子项两侧都环绕互不干扰的等宽的空白间距,最终视觉上边缘两侧的空白只有中间空白宽度一半。使用抽象图形示意如下:
space-evenly
: evenly是匀称、平等的意思。也就是视觉上,每个flex子项两侧空白间距完全相等。使用抽象图形示意如下:
5. align-items
align-items
中的items指的就是flex子项们,因此align-items
指的就是flex子项们相对于flex容器在垂直方向上的对齐方式,大家是一起顶部对齐呢,底部对齐呢,还是拉伸对齐呢,类似这样。
语法如下:
align-items: stretch | flex-start | flex-end | center | baseline;
其中:
stretch
:默认值。flex子项拉伸。在演示中我们可以看到白蓝径向渐变背景区域是上下贯穿flex容器的,就是因为flex子项的高度拉伸到容器高度导致。如果flex子项设置了高度,则按照设置的高度值渲染,而非拉伸。flex-start
:逻辑CSS属性值,与文档流方向相关。默认表现为容器顶部对齐。flex-end
:逻辑CSS属性值,与文档流方向相关。默认表现为容器底部对齐。center
:表现为垂直居中对齐。baseline
:表现为所有flex子项都相对于flex容器的基线(字母x的下边缘)对齐。
6. align-content
align-content
可以看成和justify-content
是相似且对立的属性,justify-content
指明水平方向flex子项的对齐和分布方式,而align-content
则是指明垂直方向每一行flex元素的对齐和分布方式。如果所有flex子项只有一行,则align-content
属性是没有任何效果的。
语法如下:
align-content: stretch | flex-start | flex-end | center | space-between | space-around | space-evenly;
其中:
stretch
:默认值。每一行flex子元素都等比例拉伸。例如,如果共两行flex子元素,则每一行拉伸高度是50%。flex-start
:逻辑CSS属性值,与文档流方向相关。默认表现为顶部堆砌。flex-end
:逻辑CSS属性值,与文档流方向相关。默认表现为底部堆放。center
:表现为整体垂直居中对齐。space-between
:表现为上下两行两端对齐。剩下每一行元素等分剩余空间。space-around
:每一行元素上下都享有独立不重叠的空白空间。space-evenly
:每一行元素都完全上下等分。
三、作用在flex子项上的CSS属性
1. order
我们可以通过设置order改变某一个flex子项的排序位置。
语法:
order: <integer>; /* 整数值,默认值是 0 */
所有flex子项的默认order属性值是0,因此,如果我们想要某一个flex子项在最前面显示,可以设置比0小的整数,如-1就可以了。
例如:flex容器有4个子元素,现在,我们给第2个子元素设置order属性值,看看其排列位置有何变化。点击这里看到实时的交互效果:
2. flex-grow
flex-grow
属性中的grow是扩展的意思,扩展的就是flex子项所占据的宽度,扩展所侵占的空间就是除去元素外的剩余的空白间隙。
具体的扩展比较复杂。在展开之前,我们先看下语法。
语法:
flex-grow: <number>; /* 数值,可以是小数,默认值是 0 */
flex-grow不支持负值,默认值是0,表示不占用剩余的空白间隙扩展自己的宽度。如果flex-grow
大于0,则flex容器剩余空间的分配就会发生,具体规则如下:
- 所有剩余空间总量是1。
- 如果只有一个flex子项设置了
flex-grow
属性值:- 如果
flex-grow
值小于1,则扩展的空间就总剩余空间和这个比例的计算值。 - 如果
flex-grow
值大于1,则独享所有剩余空间。
- 如果
具体可参见“grow案例1”
- 如果有多个flex设置了
flex-grow
属性值:- 如果
flex-grow
值总和小于1,则每个子项扩展的空间就总剩余空间和当前元素设置的flex-grow
比例的计算值。 - 如果
flex-grow
值总和大于1,则所有剩余空间被利用,分配比例就是flex-grow
属性值的比例。例如所有的flex子项都设置flex-grow:1,则表示剩余空白间隙大家等分,如果设置的flex-grow
比例是1:2:1,则中间的flex子项占据一半的空白间隙,剩下的前后两个元素等分。
- 如果
具体可参见“grow案例2”
3. flex-shrink
shrink
是“收缩”的意思,flex-shrink
主要处理当flex容器空间不足时候,单个元素的收缩比例。
语法如下:
flex-shrink: <number>; /* 数值,默认值是 1 */
flex-shrink不支持负值,默认值是1,也就是默认所有的flex子项都会收缩。如果设置为0,则表示不收缩,保持原始的fit-content宽度。
flex-shrink
跟flex-grow
相反,flex-grow
是空间足够时候如何扩展利用空间,flex-shrink
则是空间不足时候如何收缩腾出空间。
两者的规则也是类似。已知flex子项不换行,且容器空间不足,不足的空间就是“完全收缩的尺寸”:
- 如果只有一个flex子项设置了
flex-shrink
:flex-shrink
值小于1,则收缩的尺寸不完全,会有一部分内容溢出flex容器。flex-shrink
值大于等于1,则收缩完全,正好填满flex容器。
- 如果多个flex子项设置了
flex-shrink
:flex-shrink
值的总和小于1,则收缩的尺寸不完全,每个元素收缩尺寸占“完全收缩的尺寸”的比例就是设置的flex-shrink
的值。flex-shrink
值的总和大于1,则收缩完全,每个元素收缩尺寸的比例和flex-shrink
值的比例一样。
具体可参见“flex-shrink案例”
4. flex-basis
flex-basis
定义了在分配剩余空间之前元素的默认大小。相当于对浏览器提前告知:浏览器兄,我要占据这么大的空间,提前帮我预留好。
语法如下:
flex-basis: <length> | auto; /* 默认值是 auto */
默认值是auto,就是自动。有设置width则占据空间就是width,没有设置就按内容宽度来。
如果同时设置width和flex-basis,就渲染表现来看,会忽略width。flex顾名思义就是弹性的意思,因此,实际上不建议对flex子项使用width属性,因为不够弹性。
当剩余空间不足的时候,flex子项的实际宽度并通常不是设置的flex-basis尺寸,因为flex布局剩余空间不足的时候默认会收缩。
具体可参见“flex-basis案例”
5. flex
flex
属性是flex-grow
,flex-shrink
和flex-basis
的缩写。
语法:
flex: none | auto | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
其中第2和第3个参数(flex-shrink
和flex-basis
)是可选的。默认值为0 1 auto。
经测试发现:
flex
默认值 = flex:0 1 auto;flex:none
= flex:0 0 auto;flex:auto
= flex:1 1 auto;
具体可参见“flex案例”
6. align-self
align-self
指控制单独某一个flex子项的垂直对齐方式,写在flex容器上的这个align-items
属性,后面是items,有个s,表示子项们,是全体;这里是self,单独一个个体。其他区别不大,语法几乎一样:
align-self: auto | flex-start | flex-end | center | baseline | stretch;
auto
: 默认值,表示继承自flex容器的align-items
属性值flex-start
:逻辑CSS属性值,与文档流方向相关。默认表现为容器顶部对齐。flex-end
:逻辑CSS属性值,与文档流方向相关。默认表现为容器底部对齐。center
:表现为垂直居中对齐。baseline
:表现为所有flex子项都相对于flex容器的基线(字母x的下边缘)对齐。stretch
:flex子项拉伸。在演示中我们可以看到白蓝径向渐变背景区域是上下贯穿flex容器的,就是因为flex子项的高度拉伸到容器高度导致。如果flex子项设置了高度,则按照设置的高度值渲染,而非拉伸。
具体可参见“align-self案例”
示例中,先设置flex容器baseline对齐,然后点击对应的单选框,给第2个flex子项设置不同align-self
属性值,观察其表现:
.wrapper {
display: flex;
align-items: baseline;
height: 240px;
}
四、其他Flex知识点
- 在Flex布局中,flex子元素的设置float,clear以及vertical-align属性都是没有用的。
- Flexbox布局最适合应用程序的组件和小规模布局(一维布局),而Grid布局则适用于更大规模的布局(二维布局),关Grid布局请参见“写给自己看的display: grid布局教程”一文。
参考文章: