Flexbox 布局完全解析
Flexbox 布局完全解析
最近看到不少,关于布局的讨论,有用百分比自适应的,有用Table layout的,还有用媒体查询的,方法各式各样,每个都可以乐此不疲的讨论个大半天。不过话又说回来,程序员,尤其是搞前端的大多都是喜新厌旧的,这里准备非常非常非常详细的说一下Flexbox布局模式。
Flexbox Layout 模式,旨在实现更方便,更有效的进行布局,很久以前,在我第一次接触到这家伙的时候确实被深深的吸引了。
Flexbox相关名词
( 图片来源:https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Flexible_boxes )
感谢MDN,Flexbox的相关名词这里已经标注的足够清楚了,就不一一的去介绍他们了。
Flexbox细节
在进行Flexbox布局之前,我们要明确一点,Flexbox不应该理解成一个简单的属性,他有一个很完整的结构:容器(container)和部件(items)。所有的部件是基于容器来布局的。容器相当于一个大的房子,然后items相当于房子里面的家具,所有的家具都是相对于房子来布局的,并且一般情况下这些家具都是在房子内部的。
Container 容器
display
现在我们一起来建一栋房子(Flexbox布局的容器),这一步很简单,只要简单的通过display来进行定义就可以了。
.container{
display: flex; /*或者 inline-flex */
}
flex-direction
有了房子之后我们就可以在房子里面放置家具了。假设我们的家具必须按顺序排序(先放1号家具,再放2号家具……),那么作为房子的主人,我可以更具自己的喜好,来选择家具放置的方向(横向排、纵向排、正序排、逆序排),这时候就要用到 flex-direction
了
.container{
flex-direction: row | row-reverse | column | column-reverse;
}
flex-direction 有下面几个可用的值:
flex-direction:
- row : 默认方向,横排,从左到右
- row-reverse 横排,从又到粽
- column 纵排,从上到下
- column-reverse 纵排,从下到上
flex-wrap
当我们把所有的家具完整的摆成一排之后,突然发现了这样一个问题,还有2件家具没有地方放怎么办?
这时候 flex-wrap
就派上用场了,它用来指定一排的情况下多余的元素如何处理,他有下面的几个属性:
.container{
flex-wrap: nowrap | wrap | wrap-reverse;
}
flex-wrap:
- nowrap : 不换行
- wrap : 正常换行
- wrap-reverse : 反转换行
先说 flex-wrap:wrap
,这个很好理解,一排放不下的情况下我可以再换一行来放置我的“家具”。
再说flex-wrap:wrap-reverse
,字面上是反转换行,但是这个反转是什么意思呢?经过实验可以很容易的发现,它反转的仅仅是 cross axis
而 main axis
木有被反转(如果不明白什么是cross axis
和main axis
的话,请仔细再看一下前面的术语介绍的图片),这一点比较出乎我们的意料,需要特别留意。
最后说 flex-wrap:nowrap
如果“家具”刚好一排能放得下,那么会很好理解,但是!如果一排放不下怎么办?如果你沿着墙把所有的部件都放好之后,发现还有3个家具不够放,但是我一定要你放成一排,你会怎么做?杀了我?也许! 但是机器并不会杀了我们,他们会采取妥协的方案,等比缩小所有元素的宽度,以放下全部的部件,是不是听起来很反人类?
flex-flow
程序员们都是很懒的,因此他们发明了简写,上面介绍了 flex-direction
和 flex-wrap
, 如果我同时想指定方向和换行岂不是要写两行?
.container{
flex-direction: row ;
flex-wrap: nowrap ;
}
No! No! No! 我们有更加简单的写法
.container{
flex-flow: row nowrap ;
}
没错!flex-flow就是为了这个场景而诞生的!
.container{
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
}
justify-content
极端情况我们都解决了,现在考虑一下比较宽松的情况吧,如果我的家具不够排一排,这时候,我又想让他们看起来比较美观的话,我可以通过修改他们的对齐方式来实现:
.container {
justify-content: flex-start | flex-end | center | space-between | space-around;
}
justify-content:
-flex-start: 常规模式,以 main start
为对齐点
-flex-end: 以 main end
为对齐点
-center: 居中对齐
-space-between: 两边紧贴 main start
和 main end
中间平均分部
-space-around: 平均分部
align-items
在垂直方向我们有 align-items
来处理
.container {
align-items: flex-start | flex-end | center | baseline | stretch;
}
align-items:
-flex-start: 以 cross-start
为对齐点
-flex-end: 以 cross-end
为对齐点
-center: 居中
-baseline: 文字的基础线
-stretch: 自动伸缩
Items (部件)
order
默认情况下,flex部件是按照代码的顺序排序的,我们可以使用order
在不改变代码的情况下,修改他们的顺序。
.item {
order: <integer>;
}
flex-grow
这个属性比较特殊,grow的意思是生长,也就是说,当我的所有元素排成一排之后,剩下的空间如何去分配。
.item {
flex-grow: <number>; /* default 0 */
}
这里的grow值可以理解成,占用剩余部分的份数,比如说空余部分是230px,然后我们指定的grow一个是7,一个是3,这样的话会吧空余的部分分成10份(7+3)每份的宽度是23px(230/10),然后第一个grow占用7份也就是161px(7*23),另一个占用69px(3*23)
flex-shrink
损耗比例,和flex-grow
相反,如果容器无法放下指定的部件,那么就会平均缩小每个部件的宽度,已到达发下这么多部件的目的。
例如:Contenter的宽度是100px,然后里面有2个宽度为100px的部件,那么如果你指定了不换行的话,浏览器会自动的将这2个部件的宽度同比缩小,即每个的宽度都为50px,这样这2个部件就能放的下了。
但是,有这么一种情况,对于A、B两个部件,A说:我比B牛逼,我不要和B缩小一样的空间,我缩小的空间永远是B的一半!
这时候我们就用到了flex-shrink
.A { flex:1 1 100px; }
.B { flex:1 2 100px; }
/*flex: 1 1 100px 是 flex-grow: 1, flex-shrink: 1, flex-basis: 20em 的简写*/
这样A,B容器的宽度就分别为67px,33px
flex-basis
指定初始化时候的item的宽度,即main size
,后面的flex-grow
,flex-shrink
都是在这个基础上进行计算的。
.item {
flex-basis: <length> | auto; /* 默认 auto */
}
flex
前面也说到了,flex是 flex-grow
, flex-shrink
和 flex-basis
的简写
.item {
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}
align-self
效果类似align-items
(上面有介绍),只不过他是针对一个部件来说的,而不是所有的部件。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
综合应用
好了,让我们看一个简单的Demo,通过flex实现的一个宽度自适应的布局模型。
点击这里查看Demo(如果Demo无法预览,请在评论中告诉我,我会把demo发到你的邮箱中)
点击这里查看Demo(如果Demo无法预览,请在评论中告诉我,我会把demo发到你的邮箱中)