前言
由于Flex布局有更好的页面重排性能,并且只要学习几个CSS属性,就可以写出简洁、优雅的页面布局。因此,学习CSS布局首先精通Flex无疑是最佳的一种选择。
Flex基本概念
Flex是Flexible Box的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性,采用Flex布局的元素,称为Flex容器(flex container)。
在Flex容器中存在两条轴,默认设置是:水平主轴(main axis) 和垂直的交叉轴(cross axis)。我们可以通过修改使垂直方向变为主轴(main axis),水平方向变为交叉轴(cross axis)。
不能先入为主认为页面宽度就是水平主轴(main axis),高度就是垂直的交叉轴(cross axis),这个需要取决于当前页面主轴的方向,如果垂直方向是主轴,那么页面的高度就是main axis。
在flex容器中,每个单元块被称为flex item(项目),每个项目占据的主轴空间为main size,占据的交叉轴空间为cross size。
Flex容器
实现 flex 布局需要先指定一个容器,任何一个容器都可以被指定为 flex 布局,这样容器内部的元素就可以使用 flex 来进行布局。如果你使用块元素如 div,你就可以使用 flex,而如果你使用行内元素,你可以使用 inline-flex。
.container {
display: flex | inline-flex;
}
需要注意:当时设置容器为 flex 布局之后,每个单元块的 float、clear、vertical-align 的属性将会失效。
目前有下面六种属性可以设置在容器上,它们分别是:
- 1.flex-direction
- 2.flex-wrap
- 3.flex-flow
- 4.justify-content
- 5.align-items
- 6.align-content
1.flex-direction
决定主轴的方向(即项目的排列方向),有以下的取值
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
2.flex-wrap
决定容器内项目是否可换行。默认情况下,flex-item都排在水平的主轴线上,有以下的取值
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
3.flex-flow
flex-direction 和 flex-wrap 的简写形式,作用不是很大。平时写的话分开写就行,这样就不用记这个属性了。
.container {
flex-flow: <flex-direction> || <flex-wrap>;
}
4.justify-content
定义了项目在主轴的对齐方式。有以下的取值
.container {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
以下测试建立在主轴为水平方向,即flex-direction: row;。将以下图片往右旋转90度,那么即得到flex-direction: colum;的效果
5.align-items
定义了项目在交叉轴上的对齐方式。有以下的取值
.container {
align-items: flex-start | flex-end | center | baseline | stretch;
}
以下测试建立在主轴为水平方向,即flex-direction: row;。
6.align-content
定义了多根轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用。
比如:当flex-wrap设置为 nowrap 的时候,容器仅存在一根轴线,因为项目不会换行,就不会产生多条轴线;当flex-wrap 设置为 wrap 的时候,容器可能会出现多条轴线,这时候就可以去设置多条轴线之间的对齐方式了。有以下的取值
.container {
align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}
以下测试建立在主轴为水平方向,即flex-direction: row;flex-wrap: wrap;。
Flex项目
目前有六种属性可运用在 flex-item 项目上:
- 1.order
- 2.flex-grow
- 3.flex-shrink
- 4.flex-basis
- 5.flex
- 6.align-self
1.order
定义项目在容器中的排列顺序,数值越小,排列越靠前,默认值为 0
.flex-item {
order: <integer>;
}
在测试中,HTML结构里,虽然 -2,-1 的 item 排在后面,但是由于分别设置了 order,却能够排到最前面。
2.flex-grow
定义项目的放大比例,默认值为 0,即如果存在剩余空间,也不放大
.flex-item {
flex-grow: <number>;
}
3.flex-shrink
定义了项目的缩小比例,默认值为 1。即如果空间不足,该项目将缩小;如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。负值对该属性无效
.flex-item {
flex-shrink: <number>;
}
4.flex-basis
定义了在分配多余空间之前,项目占据的主轴空间,浏览器根据这个属性,计算主轴是否有多余空间。默认值:auto,即项目本来的大小, 这时候 item 的宽高取决于 width 或 height 的值。
.flex-item {
flex-basis: <length> | auto;
}
当主轴为水平方向的时候,当设置了 flex-basis,项目的宽度设置值会失效,flex-basis 需要跟 flex-grow 和 flex-shrink 配合使用才能发挥效果。
- 当 flex-basis 值为 0 % 时,是把该项目视为零尺寸的,故即使声明该尺寸为 140px,也并没有什么用。
- 当 flex-basis 值为 auto 时,则跟根据尺寸的设定值(假如为 100px),则这 100px 不会纳入剩余空间。
5.flex
flex-grow, flex-shrink 和 flex-basis的简写,flex 的默认值是以上三个属性值的组合。假设以上三个属性同样取默认值,则 flex 的默认值是 0 1 auto。建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值
.flex-item{
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
flex特殊取值情况有如下几种:
/* 第1种 */
.flex-item {
flex: auto;
}
.flex-item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
/* 第2种 */
.flex-item {
flex: none;
}
.flex-item {
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
}
/* 第3种 */
.flex-item {
flex: 1;
}
.flex-item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
}
/* 第4种 */
.flex-item {
flex: 0;
}
.flex-item {
flex-grow: 0;
flex-shrink: 1;
flex-basis: 0%;
}
/* 第5种 */
.flex-item {
flex: 0%;
}
.flex-item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
}
/* 第6种 */
.flex-item {
flex: 24px;
}
.flex-item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 24px;
}
/* 第7种 */
.flex-item {
flex: 2 3;
}
.flex-item {
flex-grow: 2;
flex-shrink: 3;
flex-basis: 0%;
}
/* 第8种 */
.flex-item {
flex: 11 32px;
}
.flex-item {
flex-grow: 11;
flex-shrink: 1;
flex-basis: 32px;
}
5.align-self
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
.flex-item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
这个跟 align-items 属性是一样的,只不过 align-self 是对单个项目生效的,而 align-items 则是对容器下的所有项目生效的。
补充说明
- 1.当容器的flex-wrap 为 wrap | wrap-reverse,且每个项目宽度加起来的总宽度小于容器宽度时:flex-grow 会起作用,子项会根据 flex-grow 设定的值放大(值为0和负数的项目不放大)
- 2.当容器flex-wrap 为 wrap | wrap-reverse,且每个项目宽度加起来的总宽度大于容器宽度时:首先一定会换行,换行后,每一行的右端都可能会有剩余空间,这时 flex-grow 会起作用,若当前行每个项目的 flex-grow 都为0,则剩余空间保留,若当前行存在一个项目的 flex-grow 不为0,则剩余空间会被 flex-grow 不为0的子项占据
- 3.当容器flex-wrap 为 nowrap,且每个项目宽度加起来的总宽度小于容器宽度时:flex-grow 会起作用,项目会根据 flex-grow 设定的值放大(值为0和负数的项目不放大)
- 4.当容器flex-wrap 为 nowrap,且每个项目宽度加起来的总宽度大于容器宽度时:flex-shrink 会起作用,项目会根据 flex-shrink 设定的值进行缩小(值为0和负数的项目不放大)。但这里有一个较为特殊情况,就是当这一行所有项目的 flex-shrink 都为0时,也就是说所有的项目都不能缩小,就会出现横向滚动条
- 5.总结上面四点,可以看出不管在什么情况下,在同一时间,flex-shrink 和 flex-grow 只有一个能起作用,这其中的道理细想起来也很浅显:空间足够时,flex-grow 就有发挥的余地,而空间不足时,flex-shrink 就能起作用。当然,flex-wrap 的值为 wrap | wrap-reverse 时,表明可以换行,既然可以换行,一般情况下空间就总是足够的,flex-shrink 当然就不会起作用
辅助网站
1.Flex布局生成器:loading.io/flexbox/
2.Flex布局训练网站:flexboxfroggy.com/
参考文章
1.《Flex 布局语法教程》:www.runoob.com/w3cnote/fle…
2.《30 分钟学会 Flex 布局》:zhuanlan.zhihu.com/p/25303493