Fork me on Github

关于 flexbox,网上有着非常多的文章。比如:

那为什么我还要写呢,因为 flexbox 真的很有用很好用啊 :)

有疑问的时候可以查一下 flexbox 的草案,或者找我交流啊。

#基本概念

采用 flex 布局的元素为 flex container(也叫做 flexbox),其中的所有子元素为 flex item

将元素的 display 属性设置为flex 或者为 inline-flex 就可以将一个元素设置成 flex container,其中子元素也就自动变成 flex item 了。(如果是设置成 flex 这个 container 就是 block 级别的,如果是 inline-flex 则是 inline 级别的。)

flex 布局时,可以指明是横向(row)布局,还是竖向(column)布局,默认是横向布局。两种不同的布局方式,会决定其他 flex 属性的效果。

  • main axis

    是 flex container 的主轴,其方向与 flex 布局方向一致。就是说,如果采用横向布局,则 main axis 与 CSS 坐标系的 x 轴一致,如果采用竖向布局,则 main axisy 轴一致。

  • corss axis

    是 flex container 的交叉轴,与主轴垂直。

  • main-start / main-end

    分别是 flex container 主轴的起始边和终点边。默认情况下,flex item 从 main-startmain-end 方向排列。

  • cross-start / cross-end

    分别是 flex container 交叉轴的起始边和终点边。默认情况下,flex item 在交叉轴方向上会占满 cross-startcross-end 之间的空间。

  • main size

    指 flex item宽度高度,如果是横向布局,则 main size 是指 宽度,如果是竖向布局,则 main size 是指 高度

  • cross size

    main size 类似。如果是横向布局,则 cross size高度,如果是竖向布局,则 cross size 是指 宽度

flex container 和 flex item 都有一些 flex 相关的属性可以使用。

需要说明的是,本文所有例子中右侧的 demo 区域,都已经使用了以下 html 结构:

<div class="container">
  <div class="item">1</div>
  <div class="item">2</div>
  <div class="item">3</div>
  <div class="item">4</div>
  <div class="item">5</div>
  <div class="item">6</div>
  <div class="item">7</div>
  <div class="item">8</div>
</div>

并且使用了以下 style:

.container {
  display: flex;
  background: #70F770;
}

.item {
  color: white;
  border: 1px solid #333;
}

.item:nth-child(1) {
  background: #f00;
}

.item:nth-child(2) {
  background: #a50;
}

.item:nth-child(3) {
  background: #5a0;
}

.item:nth-child(4) {
  background: #0f0;
}

.item:nth-child(5) {
  background: #0a5;
}

.item:nth-child(6) {
  background: #05a;
}

.item:nth-child(7) {
  background: #00f;
}

.item:nth-child(8) {
  background: #00a;
}

注意: 本页面使用了 autoprefixer

#container属性

flex container 有以下几种 flex 属性可以使用

  • flex-direction
  • flex-wrap
  • flex-flow
  • justify-content
  • align-items
  • align-content

下面会对每个属性进行说明,并给出例子。

#flex-direction

flex-direction 决定布局方向,也就是 main axis 的方向。

可使用以下几个值:

.container {
  flex-direction: row | row-reverse | column | column-reverse;
}

flex-direction: row 为横向布局,该值为默认值。下面的例子中可以看到,这8个 item 是横向排开的。

.container {
  flex-direction: row;
}
1
2
3
4
5
6
7
8

flex-direction: row-reverse 为横向布局,但其中的 flex item 会反方向铺展开,起点也是从最右侧(main end)开始。

.container {
  flex-direction: row-reverse;
}
1
2
3
4
5
6
7
8

column 为竖向布局

.container {
  flex-direction: column;
}
1
2
3
4
5
6
7
8

column-reverse 竖向布局。与 row-reverse 类似,其中的 flex item 也会发反方向铺展开来,起点在下侧(main end)。

.container {
  flex-direction: column-reverse;
}
1
2
3
4
5
6
7
8

#flex-wrap

当 container 的 main axis 上排不下所有的 flex item 时怎么办呢? 属性 flex-wrap 就是来解决这个问题的,这个属性可以用来决定排不下的 item 是不是要换行或者换列。其可用值如下:

.container {
  flex-wrap: nowrap | wrap | wrap-reverse;
}

nowrap 为默认值,表示不换行。(如果是采用竖向布局,则表示不换列 :)

如果 item 在主轴上排不下,比如下面的例子中,container 使用了 column 方向排序,内部的所有 item 因为 min-height 设置为 40px了,所有 item 的高度加在一起已经超过了 containter 的可用高度了。但是因为 flex-wrap 的值为 nowrap 所以并不会换列。

注意:下面的例子中,flex-directin: column,所以采用的是竖向布局,就是说 main axis 会是 y 方向。

.container {
  flex-direction: column;
  flex-wrap: nowrap;
}

.item {
  min-height: 40px;
  width: 30px;
}
1
2
3
4
5
6
7
8

flex-wrap的值 是 wrap 时, 如果所有 item 不能在主轴上一行或者一列排开,则会换行或者换列。

下面的例子中,采用竖向布局,主轴在垂直方向。因为 item 的 min-height 设为 40px,所以这些 item 并不能在一列排下。

.container {
  flex-direction: column;
  flex-wrap: wrap;
}

.item {
  min-height: 40px;
  width: 30px;
}
1
2
3
4
5
6
7
8

wrap-reverse 时,行为会与值为 wrap 时一样。但是排列时,值为 wrap 排列会从交叉轴(corss axis)的 cross start 开始,而值为 wrap-reverse 时,排列会从交叉轴的 cross end 开始

.container {
  flex-direction: column;
  flex-wrap: wrap-reverse;
}

.item {
  min-height: 40px;
  width: 30px;
}
1
2
3
4
5
6
7
8

#flex-flow

flex-flow 属性是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值为 row nowrap

.container {
  flex-flow: <flex-direction> || <flex-wrap>;
}

#justify-content

justify-content 用于描述 flex item 及其之间的"空闲空间"在 container 主轴上的对齐方式。

.container {
  justify-content: flex-start | flex-end | center | space-between | space-around;
}

flex-start 是默认值,表示 container 中的内容会分布在主轴的起始位置。

.container {
  justify-content: flex-start;
}
1
2
3
4
5
6
7
8

flex-end 则表示 container 中的内容会分布在主轴的末尾位置。

.container {
  justify-content: flex-end;
}
1
2
3
4
5
6
7
8

center 则表示 container 中的内容在主轴上居中。

.container {
  justify-content: center;
}
1
2
3
4
5
6
7
8

space-between 则表示 container 中主轴上的所有“空闲空间”会均匀分布到 item 之间

.container {
  justify-content: space-between;
}
1
2
3
4
5
6
7
8

space-around 则表示 container 中主轴上的所有“空闲空间”会均匀分布到 item 的两侧

下面的例子中,1的左边有“一份”空间,右边也有“一份”空间。2的左边和右边也同样有“一份”空间,所以可以看到1左边有“一份”空关键,而1和2之间是有“两份”的。

.container {
  justify-content: space-around;
}
1
2
3
4
5
6
7
8

#align-items

align-items 属性决定 container 中的 item 在 交叉轴cross axis 上是如何分布的。

可用值:

.container {
  align-items: flex-start | flex-end | center | baseline | stretch;
}

flex-start表示对其到 交叉轴 croass axis 的起始边(cross start)。

下面的例子没有指定flex-direction,所以默认为横向布局。

.container {
  align-items: flex-start;
}
1
2
3
4
5
6
7
8

flex-end表示对其到 交叉轴croass axis 的终点边(cross end)。

.container {
  align-items: flex-end;
}
1
2
3
4
5
6
7
8

center表示对其到 交叉轴croass axis 的中线。

.container {
  align-items: center;
}
1
2
3
4
5
6
7
8

baseline表示按照 item 中文字的基线对齐。

.container {
  align-items: baseline;
}

.item {
  font-size: 20px;
}

.item:nth-child(2n+1) {
  font-size: 28px;
}

.item:nth-child(4) {
  font-size: 50px;
}
1
2
3
4
5
6
7
8

stretch 是默认值,如果 item 的 cross size (横向布局时,即高度)没指明的话, item 会伸展开来,cross axis 方向填满。

.container {
  align-items: stretch;
}
1
2
3
4
5
6
7
8

#align-content

align-content 这个属性只有在 item 排成多行(flex-direction 是横向)或者多列(flex-direction 是竖向)的时候才生效。它决定这多行/多列的 item 整体上在 cross axis 上的分布方式。

可用值:

.container {
  align-content: flex-start | flex-end | center | space-between | space-around | stretch;
}

flex-start 表示所有 item 整体上分布在 cross axis 的起始位置(cross start)

下面的例子中,因为 item 设置了 min-width, container 上 flex-wrap 设置为 wrap 所以会换行。

.container {
  flex-direction: row;
  flex-wrap: wrap;
  align-content: flex-start;
}

.item {
  min-width: 85px;
}
1
2
3
4
5
6
7
8

flex-end 表示所有 item 整体上分布在 cross axis 的末尾位置(cross end)

.container {
  flex-direction: row;
  flex-wrap: wrap;
  align-content: flex-end;
}

.item {
  min-width: 85px;
}
1
2
3
4
5
6
7
8

center 表示所有 item 整体上在 cross axis 的中线上对齐

.container {
  flex-direction: row;
  flex-wrap: wrap;
  align-content: center;
}

.item {
  min-width: 85px;
}
1
2
3
4
5
6
7
8

space-between 表示所有每行/每列之间空间均匀分布。

.container {
  flex-direction: row;
  flex-wrap: wrap;
  align-content: space-between;
}

.item {
  min-width: 85px;
}
1
2
3
4
5
6
7
8

space-around 表示所有每行/每列两边的空间均匀分布。

.container {
  flex-direction: row;
  flex-wrap: wrap;
  align-content: space-around;
}

.item {
  min-width: 85px;
}
1
2
3
4
5
6
7
8

stretch 是默认值, 表示行/列都将会自由拉伸开,cross axis 上占用整个空间。

.container {
  flex-direction: row;
  flex-wrap: wrap;
  align-content: stretch;
}

.item {
  min-width: 85px;
}
1
2
3
4
5
6
7
8

#item属性

flexbox 中的 item 也有着相关的 flex 属性。

  • order
  • flex-grow
  • flex-shrink
  • flex-basis
  • flex
  • align-self

#order

默认情况下,flex item 在 container 中分布时会按照 html 代码中的顺序。但我们也可以使用 order 属性来控制 item 的分布顺序。

order 的值是一个整数。初始默认值是0,值越小,就会排的越靠前,这个值也可以是负值。

.item {
  order: <integer>; /* default 0 */
}

注意观察下面例子中 item 的顺序。

.item:nth-child(2n) {
  order: -1;
}

.item:nth-child(5) {
  order: 3;
}

.item:nth-child(3) {
  order: 99;
}
1
2
3
4
5
6
7
8

#flex-grow

flex-grow 属性决定这个 item 所占空间比例

其值是一个不小于0的数字,注意该值并不是作为百分比来解释。默认值是0

.item {
  flex-grow: <number>; /* default 0 */
}

flex-grow 是如何工作的? flexbox 中的 item 在 main axis 上的尺寸首先由其 flex-basis 属性(该属性后面会进行描述)决定,假设这时 main axis 上还有“空闲空间”的话,就把这些空间分给使用了 flex-grow 属性的那些 item,flex-grow 的值就是它们额外可以拿到的空间的份数

假设只有一个 item 使用了 flex-grow 属性,则其值是 1 还是 100,其结果会是一样的,因为只有这一个 item 去分多余的“空闲空间”。

.item:nth-child(1) {
  flex-grow: 1;
}

.item:nth-child(3) {
  flex-grow: 2;
}

.item:nth-child(5) {
  flex-grow: 4;
}
1
2
3
4
5
6
7
8

#flex-shrink

flex-shrink 属性决定空间不足时这个 item 收缩的比例,默认值是1。

.item {
  flex-shrink: <number>; /* default 1 */
}
.item {
  flex-basis: 190px;
  flex-shrink: 1;
}

.item:nth-child(3) {
  flex-shrink: 2;
}

.item:nth-child(5) {
  flex-shrink: 0;
}
1
2
3
4
5
6
7
8

#flex-basis

flex-basis 表示在分配空闲空间之前 item 的 main size 的初始大小。

它可以使用与 width/height 属性相同的值,比如20px, 30%, 4em 等。除此之外,还有一个值 content, 表示尺寸基于 item 的内容, 相当与width: auto; flex-basis: auto;

默认值是 auto,表示 如果该 item 定义了 main size 尺寸则使用该尺寸,如果没有,则基于其内容。

.item:nth-child(2) {
  width: 20px;
  flex-basis: auto;
}

.item:nth-child(4) {
  flex-basis: 20%;
}
1
2
3
4
5
6
7
8

#flex

flexflex-grow, flex-shrink, flex-basis 三个属性的简写形式。

常见值:

initial

等价于 0 1 auto。 item 的大小会遵守其 width/height 属性,如果 mian size 计算出来的是 auto,则 item 的大小是由其内容决定的。如果 container 仍然有可用空间,item 并不会伸展。但如果 container 的空间不足, item 会尽可能的缩小。

auto

等价于 1 1 auto。item 的大小会遵守其 width/height 属性,但该 item 可以伸展。假设 container 中所有的 item 使用都是 flex: auto, flex: initial 或者 flex: none,当所有 item 的尺寸计算完毕以后,空余的空间会被平均分配给属性 flex: auto 的 item。

none

等价与 0 0 auto。item 的大小会遵守其 width/height 属性,但不会有伸缩性。

flex: <positive-number>

等价与 flex: <positive-number> 1 0。该 item 会完全按照指定的比例去使用空闲空间。

#align-self

align-self 属性可以用来设置该 item 在 cross axis 上的对齐方式,用来覆盖在 flex container 上的相关属性设置。

其可用值与 containeralign-items 的值一致。

.item {
  align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
.item:nth-child(2) {
  align-self: flex-end;
}

.item:nth-child(3) {
  align-self: center;
}

.item:nth-child(7) {
  font-size: 10px;
  align-self: baseline;
}

.item:nth-child(8) {
  font-size: 25px;
  align-self: baseline;
}
1
2
3
4
5
6
7
8

以上就是所有内容了,怎么样,会用了没。