CSS3学习之Flexible Box

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 属性为 flexinline-flex 声明的,即采用flex布局的容器元素;flex容器内的子元素称为flex项目,flex项目会采用flex布局模型摆放。

下面是 w3 官网上的一张图片,描述了Flexbox布局的基本概念:

flex容器默认存在两根轴:水平方向的主轴(main axis)和垂直方向的交叉轴(cross axis),主轴的起点和终点分别称作 main startmain end,交叉轴的起点和终点分别称作 cross startcross 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代码:

1
2
3
4
5
6
7
8
9
10
11
.flex-demo {
display: flex;
border: 1px solid green;
}
.flex-demo div {
width: 120px;
height: 40px;
background-color: red;
color: white;
margin: 4px;
}
  • flex-direction 属性默认值为 row,也就是说项目 从左向右 排列:
DIV#1
DIV#2
DIV#3
  • flex-direction 属性取值为 row-reverse 时,项目 从右向左 排列:
1
.flex-demo-1 {flex-direction: row-reverse;}
DIV#1
DIV#2
DIV#3
  • flex-direction 属性取值为 column 时,项目 从上向下 排列:
1
.flex-demo-2 {flex-direction: column;}
DIV#1
DIV#2
DIV#3
  • flex-direction 属性取值为 column-reverse 时,项目 从下向上 排列:
1
.flex-demo-2 {flex-direction: column-reverse;}
DIV#1
DIV#2
DIV#3

flex-wrap

flex-wrap 属性控制flex容器是单行还是多行,以及交叉轴的方向;也就是说 flex-wrap 属性可以设置当flex容器主轴一行排不下时,项目要不要换行,以及如果换行了,新行如何排列(交叉轴方向)。

属性值 说明
nowrap 默认值,表示不换行,flex容器是单行
wrap 换行,flex容器是多行
wrap-reverse 换行,flex容器是多行,同时交叉轴反转

1) nowrap(默认值):不换行

1
.flex-demo-4 {width: 300px;}
DIV#1
DIV#2
DIV#3

可以看到,将flex容器宽度定为300px时,一行已经放不下三个120px宽度的色块了,这时flex项目自己的宽度(前面设置了宽度为120px)不起作用了,每个都被压缩,但仍然没有换行。

2) wrap:换行

1
2
3
4
.flex-demo-5 {
width: 300px;
flex-wrap: wrap;
}
DIV#1
DIV#2
DIV#3

flex-wrap 属性设置为 wrap 后,一行排不下时项目换行了。

3) wrap-reverse:换行

1
2
3
4
.flex-demo-6 {
width: 300px;
flex-wrap: wrap-reverse;
}
DIV#1
DIV#2
DIV#3

flex-wrap 属性设置为 wrap-reverse 后,项目换行了,但新增的行跑到了上面,这就是反转交叉轴的效果。

flex-flow

flex-flow 属性是 flex-direction 属性和 flex-wrap 属性的简写形式,其默认值为 row nowrap,一定要保证两个属性的顺序不能错。

1
2
3
4
.flex-demo-7 {
flex-flow: column wrap-reverse;
height: 80px;
}
DIV#1
DIV#2
DIV#3

justify-content

justify-content 定义flex项目在容器主轴上的对齐方式,其所有可设置的值都列举在下方的表格中,具体对齐方式其实与主轴的方向有关。

属性值 说明
flex-start 默认值,项目向主轴起点(main start)对齐
flex-end 项目向主轴终点(main end)对齐
center 居中对齐
space-between 两端对齐,项目之间的间隔都相等
space-around 每个项目两侧间隔相等,项目间的间隔比项目与边框的间隔大一倍

justify-content属性
上面的图片可以很形象地说明各值的意思,但要注意地是图片中展示的是 flex-direction 取值为 row 的情况,flex-startflex-end 不能简单地理解为“左对齐”和“右对齐”,下面用一个示例说明一下:

1
2
3
4
.flex-demo-8 {
flex-direction: row-reverse;
justify-content: flex-end;
}
DIV#1
DIV#2
DIV#3

可以看到,在 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,将占满整个容器的高度

align-items
justify-content 属性类似,上面的图片展示的仍是 flex-direction 取值为 row 的情况,具体情况还是要考虑交叉轴的方向。下面几个示例演示了 align-items 属性几个取值的对齐效果。

1) stretch(默认值):项目未设置高度或设为auto,将占满整个容器的高度

1
2
.flex-demo-9 div {height: auto;}
.flex-demo-9 {height: 60px;}
DIV#1
DIV#2
DIV#3

2) flex-end:向交叉轴终点对齐

1
2
.flex-demo-10 div:last-of-type {height: 60px;}
.flex-demo-10 {align-items: flex-end;}
DIV#1
DIV#2
DIV#3

3) center:在交叉轴方向上居中对齐,向交叉轴中点对齐

1
2
.flex-demo-11 div:last-of-type {height: 60px;}
.flex-demo-11 {align-items: center;}
DIV#1
DIV#2
DIV#3

4) baseline:向flex项目的第一行文字基线对齐

1
2
3
4
5
.flex-demo-12 div:last-of-type {
height: 60px;
padding-top: 12px;
}
.flex-demo-12 {align-items: baseline;}
DIV#1
DIV#2
DIV#3

align-content

align-content 属性定义当flex容器在交叉轴方向上有多余空间时,将单行看成独立单位,这些行在交叉轴上的对齐方式,这与 justify-content 属性类似。

当flex容器只有单行时,该属性没有效果

属性值 说明
flex-start 与交叉轴的起点对齐
flex-end 与交叉轴的终点对齐
center 与交叉轴的中点对齐,即居中对齐
space-between 与交叉轴两端对齐,轴线之间的间隔平均分布
space-around 每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍
stretch 默认值,轴线占满整个交叉轴

下面的图片取自 w3 官网,它(假设交叉轴从上向下)描述了 align-content 属性各个取值所形成的效果:
align-content

1) 上面示例代码当交叉轴上有多余空间时

1
2
3
4
5
.flex-demo-01 {
width: 440px;
height: 180px;
flex-wrap: wrap;
}
DIV#1
DIV#2
DIV#3
DIV#4
DIV#5

这个效果看起来很怪异,这其实是因为我们限制了每个项目的高度,使其不能正常拉伸(align-content 属性默认值是 stretch);但第二行的起点是在容器的中点,其它这两行仍然占据了整个容器,但由于项目高度被固定,导致无法拉伸。

2) 这时就体现 align-content 其它值的作用了,设置为 center 试一下:

1
.flex-demo-02 {align-content: center;}
DIV#1
DIV#2
DIV#3
DIV#4
DIV#5

可以看到,当我们设置 align-contentcenter 后,它们很“听话”地居中对齐了。

3) 再演示一个两端对齐的,其它几种对齐就不再演示了,很简单:

1
.flex-demo-03 {align-content: space-around;}
DIV#1
DIV#2
DIV#3
DIV#4
DIV#5

4) 我们将上面的示例改一下,去掉项目的高度设置

1
.flex-demo-04 div {height: auto;}
DIV#1
DIV#2
DIV#3
DIV#4
DIV#5

很明显,在去掉项目的高度设置后,拉伸效果出现了。

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。

1
.flex-demo-13 div:last-of-type {order: -1;}
DIV#1
DIV#2
DIV#3

从上面的示例可以看出,将第三个DIV的 order 属性设置为-1后,由于另外两个排在前面的DIV的 order 属性都为默认值0,因此它排在了最前面。

flex-grow

flex-grow 属性指定如果容器存在剩余空间时项目的扩展倍数,属性值是一个非负数字,默认值为0,表示不扩展。如果容器内所有项目的 flex-grow 属性值都相同且不为0,那它们会等分所有剩余空间;如果不相等,它们会按照 flex-grow 值的比例来分配剩余空间。

注意:flex-grow 属性值如果设置为负数,则此属性无效

1) 仅把第三个DIV的 flex-grow 属性设置为1,它会占据所有剩余空间:

1
.flex-demo-14 div:last-of-type {flex-grow: 1;}
DIV#1
DIV#2
DIV#3

2) 将第一个和第三个DIV的 flex-grow 属性分别设置为2和1,它们会按2:1的比例占据剩余空间:

1
2
.flex-demo-15 div:first-of-type {flex-grow: 2;}
.flex-demo-15 div:last-of-type {flex-grow: 1;}
DIV#1
DIV#2
DIV#3

3) 所有DIV的 flex-grow 属性值相同时,它们会平分容器剩余空间:

1
.flex-demo-16 div {flex-grow: 2;}
DIV#1
DIV#2
DIV#3

flex-shrink

flex-shrink 属性与 flex-grow 属性相反,定义当容器空间不足时项目的收缩比例,同样接受一个数字为属性值,默认值为1,表示容器空间不足时所有项目等比例缩小。如果设置为0,表示该项目不收缩。

注意:flex-shrink 属性值如果设置为负数,则此属性无效

1
2
.flex-demo-17 {width: 300px;}
.flex-demo-17 div:last-of-type {flex-shrink: 0}
DIV#1
DIV#2
DIV#3

从上面的示例可以看出,第三个DIV的 flex-shrink 属性设置为0后,它在容器空间不足时保持不变,其它两个DIV等比例缩小。下面再看一个不等比例缩小的示例:

1
2
3
.flex-demo-18 {width: 300px;}
.flex-demo-18 div:last-of-type {flex-shrink: 2}
.flex-demo-18 div:nth-of-type(2) {flex-shrink: 0}
DIV#1
DIV#2
DIV#3

上面的示例中,第二个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-growflex-shrinkflex-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 属性的取值完全一样。

1
2
.flex-demo-19 {height: 60px;}
.flex-demo-19 div:first-of-type {align-self: flex-end;}
DIV#1
DIV#2
DIV#3
DIV#4

从上面示例可以看出,第一个项目的 align-self 属性设置为 flex-end,其它三个项目没有设置,表示继承父容器的 align-items 属性,而 align-items 属性默认是 flex-start ;这就造成了上面的效果,第一个项目独自向交叉轴底端对齐,而其它三个项目都是向交叉轴起点对齐。

总结

本文只是简单地解释了Flexbox布局的基本概念及其相关属性,其实这些属性组合起来使用是很复杂的,比如 flex-basis 等,还需要进一步学习和实践。

一些资料:

文章目录
  1. 1. Flexbox 概念
  2. 2. Flex容器的属性
    1. 2.1. flex-direction
    2. 2.2. flex-wrap
    3. 2.3. flex-flow
    4. 2.4. justify-content
    5. 2.5. align-items
    6. 2.6. align-content
  3. 3. Flex项目的属性
    1. 3.1. order
    2. 3.2. flex-grow
    3. 3.3. flex-shrink
    4. 3.4. flex-basis
    5. 3.5. flex
    6. 3.6. align-self
  4. 4. 总结
|