前言
如果您对flex布局的基本概念还没有了解的话,建议先看一下阮一峰老师的文章Flex布局.语法篇。
阮老师的文章图文并茂,对flex box的基本语法和概念解释的非常清楚。
我的这篇文章只是在此基础上进行了整理归类,flex box 中的一些概念定义得并不是很直观,不太容易记忆,一段时间不使用就会感到陌生。我从日常使用的角度对这些概念进行了归类,并绘制了脑图,出发点是在自己出现遗忘的时候瞟一下脑图就能重新想起来。
1. 重要概念
flex布局意为弹性布局,为盒模型提供最大的灵活性。任何一个容器都可以指定为flex布局。
设置flex布局非常简单:
.container {
display: flex;
}
flex布局中有几个重要的概念:
用于放置内容的容器container, 水平方向的主轴main axis, 垂直方向的交叉轴cross axis, 还有需要布局的项目item。
主轴类似于x坐标轴,交叉轴类似于y坐标轴,可以把container想象成是放置于第四象限中进行布局的。 具体可以参考软来时博客中的图片。
2. 整体container布局
2.1 设置对齐方式
2.1.1 设置主轴方向对齐方式
设置justify-content属性
.container {
justify-content: flex-start | flex-end | cneter | baseline | strech
}
- flex-start:从左往右
- flex-end:从右往左
- center: 水平居中
- space-between:两端对齐,项目之间的间隔相等
- space-around: 项目左右两侧的间隔相等。项目之间的间隔是项目与边框之间间隔的两倍。
几种取值情况的水平对齐方式如下图所示:
2.1.2 设置交叉轴方向对齐方式
2.1.2.1 一根交叉轴的对齐方式
align-items
.container {
align-items: flex-start | flex-end | center | space-between | space-around
}
2.1.2.2 多根轴线的对齐方式
align-content 对多行item进行对齐时需要使用align-content,该属性对于单行的情形是不适用的。
设置水平垂直居中
设置水平垂直居中对齐
.container {
display: flex;
justify-content: center;
align-items: center;
}
使用flex布局来设置水平垂直居中就非常轻松了,不再需要使用hack技巧。
2.2 设置项目排列方向
flex-direction
.container {
flex-direction: row | row-reverse | column | column-reverse
}
- row: 主轴在水平方向,从左往右排列;默认值;
- row-reverse: 主轴在水平方向,从右往左排列;
- column: 主轴在垂直方向,从上往下;
- coumn-reverse: 主轴在垂直方向,从下往上;
2.3 设置换行方式
flex-wrap
.container {
flex-wrap: nowrap | wrap | wrap-reverse
}
- nowrap: 不换行;
- wrap: 换行,第一行在上方,剩下的往下排;
- wrap-reverse: 换行,第一行在下方,剩下的往上排;
3.单个item设置
前面都是针对整个container容器进行的设置,从全局角度对item的对齐方式、排列走向、换行方式进行统一的的设置。
但是这样的设置不一定能满足所有的需求,有的时候某些item会有与众不同的布局需求,需要对某一个后几个item进行定制化设置。这种情况下你就需要针对具体的item的属性进行设置了。
- order
- align-self
- flex-grow
- flex-shrink
- flex-basis
order: 设置单个item的排列顺序,数值越大越靠前;
.item {
order: <integer>;
}
align-self: 设置单个item的排列方式,可以和整体排列方式不一样;
.item: {
flex-grow: <number>;
}
后面3个属性 flex-grow | flex-shrink | flex-basis 可以合并成一个属性flex。 这个flex不是很直观,不太好记忆,为了便于理解记忆,我这里用一个可能不是太贴切比喻来解释这个概念。
flex-grow: 定义如果container中有剩余空间,是否放大item,默认值为0,意为即使有剩余空间也不放大。如果全部为1,即为等比例放大;如果一项为2,其他项为1,则前者占据的剩余空间要比后者多一倍。
.item {
flex-grow: <number>; // 默认为0;即使空间没有使用完,也不填充。
}
这段话如果理解了也就理解了,如果没理解,请看这个例子:
有一天小明和小强加完班后坐末班地铁,地铁上很空位置很多。小明和小强找了一排位置坐下了,一排一共有6个座位,小明坐第一个,小强坐第二个,剩下4个座位都是空着的。那么布局如下:
然后小明很困了,小强也眯着眼睛在座位上快睡着了。看到还有很多空余位置,小明便对小强说,你往那边挪挪,咱们都躺下眯一会儿吧。于是小强挪到了第4个位置上,他们把剩下的位置平均分了。
于是属性设置便是这样的:
.itemMing, .itemQiang {
flex-grow: 1; // 剩余空间被等比例分配了
}
但是后来他们发现剩余的位置需要重新分配,因为小明身材非常高大,小强比较矮小。于是善良的小强往后挪了挪,又腾了1/3个位置给小明,这样剩下的4个位置中,小明分了2.6个,小强1.3个,小明是小强的2倍。
于是属性设置变成了这样:
.itemMing {
flex-grow: 2;
}
.itemQiang {
flex-grow: 1;
}
位置的分配变成了这样:
flex-shrink: 定义单个item的缩小比例,可以避免内容从父容器中溢出;
.item {
flex-shrink: <number> // 默认为1;空间不足时item将缩小,避免溢出容器。
}
如果所有的item该属性都为1,那么空间不足时,将等比例缩小;如果有一项为0,其他项都为1,那么前者不缩小,其他项目等比例缩小。
理解的就理解了,没理解的看看例子:
有一天小明小强和同事们一起出去团建,大家选择了地铁出行。 大家幸运的发现了一排空座位,但不巧的是座位有6个,但是小明同事一行有7个人,空间不足了,有一个同学没位置坐。 于是谦虚的小强同学说,你们坐吧,我站一会儿就行,于是小明从容器中溢出了。这怎么好意思呢?好基友小明同学说,大家挤挤吧,给小强腾个位置。于是大家腾出了一点位置,小强同学坐下了。
这个例子中,大家占据的位置等比例缩小了,item设置是这样的:
.item {
flex-shrink: 1; // 空间不足时,大家一起shrink, 溢出问题得到解决。
}
但是问题来了,大家突然想起来小花同学是个孕妇,怎么能让她跟大家一起挤呢?于是小明又发话了,小花你坐到孕妇专座上别动,不要跟大家一起挤。
于是设置变成了这样:
.item:not(#itemHua) {
flex-shrink: 1;
}
#itemHua {
flex-shrink: 0;
}
flex-basis: 设置分配多余空间之前单个item占据的主轴空间。
.item {
flex-basis: <length> | auto; // 默认值为auto,即项目本来的大小
}
后面三个属性可以合并为一个属性flex; 后面两个属性可选。
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
该属性有几个快捷值:
- flex: initial;
- flex: auto;
- flex: none;
- flex:
flex: initial; 等同于flex: 0 1 auto;
全部使用默认值。空间不足时缩小,有余时不变;
flex: auto; 等同于 flex: 1 1 auto;
空间有剩余时放大,空间不足时缩小;
flex: none; 等同于 flex: 0 0 auto; // 不论剩余空间大小,始终保持不变;
flex: 1; 等同于 flex: 1 1 0;
.item {flex: 1;}
// 等同于
.item {
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0%;
}
建议优先使用合并属性,不推荐分开写。 flex值的这种缩写可以参考segmentfault的这篇文章。
4.总结
见脑图。
另外归纳一下水平和垂直对齐属性的特点: 水平对齐的属性比较单纯,只有一个,justify-content;
垂直方向的对齐属性有三个:
- align-items: 最常用,针对单行单列的布局设置垂直对齐方式;
- align-content: 针对多轴线(交叉轴)的布局设置垂直方向的对齐方式,也就是用于多行多列的布局中,只有一根轴线的情况下是不适用的。
- align-self: 针对单个item设置垂直方向的对齐方式。