Flexible Box(也叫Flexbox)是CSS3新增的一种可伸缩的灵活的Web页面布局方式,使用它可以使Web页面在不同设备及不同屏幕上显示地更加友好。
首先看一下Flexbox浏览器兼容情况:
Property | Chrome | IE | Firefox | Safari | Opera |
---|---|---|---|---|---|
Basic support (single-line flexbox) |
29.0 21.0 -webkit- |
11.0 | 22.0 18.0 -moz- |
6.1 -webkit- | 12.1 -webkit- |
Multi-line flexbox | 29.0 21.0 -webkit- |
11.0 | 28.0 | 6.1 -webkit- | 17.0 15.0 -webkit- |
Flexbox 概念
Flexbox由flex容器(flex container)和flex项目(flex items)组成,flex容器是HTML元素通过设置 display
属性为 flex
或 inline-flex
声明的,即采用flex布局的容器元素;flex容器内的子元素称为flex项目,flex项目会采用flex布局模型摆放。
下面是 w3 官网上的一张图片,描述了Flexbox布局的基本概念:
flex容器默认存在两根轴:水平方向的主轴(main axis)和垂直方向的交叉轴(cross axis),主轴的起点和终点分别称作 main start
和 main end
,交叉轴的起点和终点分别称作 cross start
和 cross end
。
flex项目默认沿主轴排列,单个项目占据的主轴空间叫作 main size
,占据的交叉轴空间叫作 cross size
。
Flex容器的属性
flex容器一共有以下几个相关属性:
属性 | 说明 |
---|---|
flex-direction | 决定主轴的方向,也就flex项目排列的方向,默认值为row,表示从左向右排列 |
flex-wrap | 指定主轴上一行排不下时,项目如何换行,默认值为nowrap,表示不换行 |
flex-flow | flex-direction 和 flex-wrap 两个属性的简写属性,默认值为 row nowrap |
justify-content | 定义flex项目在主轴上的对齐方式 |
align-items | 定义flex项目在交叉轴上如何对齐 |
align-content |
flex-direction
flex-direction
属性通过指定flex容器主轴的方向来设置flex项目在容器中排列的方向,下面表格中列举了 flex-direction
属性所有可设置的值,在W3官方文档中介绍 flex-direction
属性时引入了 writing mode 的概念,由于我们的书写方向都是从左往右、自上而下,因此下面的解释直接使用上下左右的方向概念。
属性值 | 说明 |
---|---|
row | 默认值,主轴为水平方向,起点在左端,也就是说项目自左向右排列 |
row-reverse | 主轴为水平方向,起点在右端,项目自右向左排列 |
column | 主轴为垂直方向,起点在顶端,项目从上往下排列 |
column-reverse | 主轴为垂直方向,起点在底端,项目从下往上排列 |
下面用示例来演示一下,以下示例的公共CSS代码:
|
|
flex-direction
属性默认值为row
,也就是说项目 从左向右 排列:
flex-direction
属性取值为row-reverse
时,项目 从右向左 排列:
|
|
flex-direction
属性取值为column
时,项目 从上向下 排列:
|
|
flex-direction
属性取值为column-reverse
时,项目 从下向上 排列:
|
|
flex-wrap
flex-wrap
属性控制flex容器是单行还是多行,以及交叉轴的方向;也就是说 flex-wrap
属性可以设置当flex容器主轴一行排不下时,项目要不要换行,以及如果换行了,新行如何排列(交叉轴方向)。
属性值 | 说明 |
---|---|
nowrap | 默认值,表示不换行,flex容器是单行 |
wrap | 换行,flex容器是多行 |
wrap-reverse | 换行,flex容器是多行,同时交叉轴反转 |
1) nowrap
(默认值):不换行
|
|
可以看到,将flex容器宽度定为300px时,一行已经放不下三个120px宽度的色块了,这时flex项目自己的宽度(前面设置了宽度为120px)不起作用了,每个都被压缩,但仍然没有换行。
2) wrap
:换行
|
|
flex-wrap
属性设置为 wrap
后,一行排不下时项目换行了。
3) wrap-reverse
:换行
|
|
flex-wrap
属性设置为 wrap-reverse
后,项目换行了,但新增的行跑到了上面,这就是反转交叉轴的效果。
flex-flow
flex-flow
属性是 flex-direction
属性和 flex-wrap
属性的简写形式,其默认值为 row nowrap
,一定要保证两个属性的顺序不能错。
|
|
justify-content
justify-content
定义flex项目在容器主轴上的对齐方式,其所有可设置的值都列举在下方的表格中,具体对齐方式其实与主轴的方向有关。
属性值 | 说明 |
---|---|
flex-start | 默认值,项目向主轴起点(main start)对齐 |
flex-end | 项目向主轴终点(main end)对齐 |
center | 居中对齐 |
space-between | 两端对齐,项目之间的间隔都相等 |
space-around | 每个项目两侧间隔相等,项目间的间隔比项目与边框的间隔大一倍 |
上面的图片可以很形象地说明各值的意思,但要注意地是图片中展示的是 flex-direction
取值为 row
的情况,flex-start
和 flex-end
不能简单地理解为“左对齐”和“右对齐”,下面用一个示例说明一下:
|
|
可以看到,在 flex-direction
属性设置为 row-reverse
时,flex-end
也实现了左对齐。这其实是因为 row-reverse
改变了主轴的方向(改为从右向左),使主轴起点在右侧,终点在左侧,那么 flex-end
正好是向主轴终点靠齐,因此实现了“左对齐”。
align-items
align-items
属性用来定义flex项目在交叉轴上的对齐方式,与 justify-content
属性类似,具体的对齐方式与交叉轴的方向有关;但该属性默认值不再是向交叉轴起点对齐,而是在交叉轴方向上没有具体尺寸时会被拉伸以适应容器尺寸。
属性值 | 说明 |
---|---|
flex-start | 向交叉轴的起点对齐 |
flex-end | 向交叉轴的终点对齐 |
center | 居中对齐,向交叉轴的中点对齐 |
baseline | 向flex项目的第一行文字基线对齐 |
stretch | 默认值,如果项目未设置高度或设为auto,将占满整个容器的高度 |
与 justify-content
属性类似,上面的图片展示的仍是 flex-direction
取值为 row
的情况,具体情况还是要考虑交叉轴的方向。下面几个示例演示了 align-items
属性几个取值的对齐效果。
1) stretch
(默认值):项目未设置高度或设为auto,将占满整个容器的高度
|
|
2) flex-end
:向交叉轴终点对齐
|
|
3) center
:在交叉轴方向上居中对齐,向交叉轴中点对齐
|
|
4) baseline
:向flex项目的第一行文字基线对齐
|
|
align-content
align-content
属性定义当flex容器在交叉轴方向上有多余空间时,将单行看成独立单位,这些行在交叉轴上的对齐方式,这与 justify-content
属性类似。
当flex容器只有单行时,该属性没有效果
属性值 | 说明 |
---|---|
flex-start | 与交叉轴的起点对齐 |
flex-end | 与交叉轴的终点对齐 |
center | 与交叉轴的中点对齐,即居中对齐 |
space-between | 与交叉轴两端对齐,轴线之间的间隔平均分布 |
space-around | 每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍 |
stretch | 默认值,轴线占满整个交叉轴 |
下面的图片取自 w3 官网,它(假设交叉轴从上向下)描述了 align-content
属性各个取值所形成的效果:
1) 上面示例代码当交叉轴上有多余空间时
|
|
这个效果看起来很怪异,这其实是因为我们限制了每个项目的高度,使其不能正常拉伸(align-content
属性默认值是 stretch
);但第二行的起点是在容器的中点,其它这两行仍然占据了整个容器,但由于项目高度被固定,导致无法拉伸。
2) 这时就体现 align-content
其它值的作用了,设置为 center
试一下:
|
|
可以看到,当我们设置 align-content
为 center
后,它们很“听话”地居中对齐了。
3) 再演示一个两端对齐的,其它几种对齐就不再演示了,很简单:
|
|
4) 我们将上面的示例改一下,去掉项目的高度设置
|
|
很明显,在去掉项目的高度设置后,拉伸效果出现了。
Flex项目的属性
flex项目也有自己的属性,如下所示:
属性 | 说明 |
---|---|
order | 定义项目间的顺序,数值越小越靠前,默认为0。 |
flex-grow | 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大 |
flex-shrink | 定义项目的收缩比例,默认为1,即如果空间不足,该项目将缩小 |
flex-basis | |
flex | 是flex-grow、flex-shrink和flex-basis的简写,默认值为0 1 auto,后两个属性可选 |
align-self | 设置项目的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch |
order
order
属性用来定义项目间的顺序,属性值是整数(正数、负数和零都可以),数值越小项目越靠前,默认值为0。
|
|
从上面的示例可以看出,将第三个DIV的 order
属性设置为-1后,由于另外两个排在前面的DIV的 order
属性都为默认值0,因此它排在了最前面。
flex-grow
flex-grow
属性指定如果容器存在剩余空间时项目的扩展倍数,属性值是一个非负数字,默认值为0,表示不扩展。如果容器内所有项目的 flex-grow
属性值都相同且不为0,那它们会等分所有剩余空间;如果不相等,它们会按照 flex-grow
值的比例来分配剩余空间。
注意:
flex-grow
属性值如果设置为负数,则此属性无效
1) 仅把第三个DIV的 flex-grow
属性设置为1,它会占据所有剩余空间:
|
|
2) 将第一个和第三个DIV的 flex-grow
属性分别设置为2和1,它们会按2:1的比例占据剩余空间:
|
|
3) 所有DIV的 flex-grow
属性值相同时,它们会平分容器剩余空间:
|
|
flex-shrink
flex-shrink
属性与 flex-grow
属性相反,定义当容器空间不足时项目的收缩比例,同样接受一个数字为属性值,默认值为1,表示容器空间不足时所有项目等比例缩小。如果设置为0,表示该项目不收缩。
注意:
flex-shrink
属性值如果设置为负数,则此属性无效
|
|
从上面的示例可以看出,第三个DIV的 flex-shrink
属性设置为0后,它在容器空间不足时保持不变,其它两个DIV等比例缩小。下面再看一个不等比例缩小的示例:
|
|
上面的示例中,第二个DIV固定不变,第三个DIV的 flex-shrink
属性设置为2,第一个DIV取默认值1,最终第一个DIV和第三个DIV的缩小比例为1:2,也就是说第三个DIV的收缩量是第一个DIV的2倍。从最终效果上也可以看出,第三个DIV更短一些。
flex-basis
flex-basis
属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小(即 width
属性设置的值,没有设置则是内容撑开的尺寸)。
如果设置了
flex-basis
属性,那么width
属性会被忽略(覆盖),也就是说flex-basis
的优先级比width
要高
flex-basis
属性可以设置为跟 width 或 height 属性一样的值(比如350px或20%等),则项目向父容器预约指定尺寸的宽度,然后才会根据情况收缩或扩展。
flex
flex
属性是 flex-grow
、flex-shrink
和 flex-basis
的简写属性,默认值为 0 1 auto
,后两个属性是可选的。该属性有两个快捷值:auto(1 1 auto)和 none(0 0 auto)。
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
align-self
align-self
属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items
属性。align-self
属性默认值为auto,表示继承父元素的 align-items
属性,如果没有父元素,则等同于 stretch
。
该属性可以设置的6个值除了 auto
外,其它5个值与 align-items 属性的取值完全一样。
|
|
从上面示例可以看出,第一个项目的 align-self
属性设置为 flex-end
,其它三个项目没有设置,表示继承父容器的 align-items
属性,而 align-items
属性默认是 flex-start
;这就造成了上面的效果,第一个项目独自向交叉轴底端对齐,而其它三个项目都是向交叉轴起点对齐。
总结
本文只是简单地解释了Flexbox布局的基本概念及其相关属性,其实这些属性组合起来使用是很复杂的,比如 flex-basis
等,还需要进一步学习和实践。
一些资料: