理解 Flexbox:你需要知道这些

flexbox 顾名思义 flexible box 弹性盒子,是 css3 中定义的一种新的布局方式。通过在某元素上使用 display: flex; 即可把该元素定义为 flex 容器 ( flex container ),而容器的所有子元素就是 flex 项目 ( flex item )。再介绍 flex 语法之前,先来看看一个重要的东西。

flex 轴线

flex_axis.png

flex 容器里,存在两条轴,main axiscross axis,又分别叫做主轴和交叉轴。主轴之所以叫做主轴而不叫做 x 轴,是因为主轴不一定是在水平线上的,也有可能是垂直方向上,比如当 flex-direction: column; 的时候,主轴就是在垂直方向上。另外主轴和交叉轴都是有方向的,flex` 项目就是沿着主轴方向进行布局。主轴默认方向是从左到右,交叉轴则是从上到下。

css3 里关于 flexbox 定义了 2 类的样式,分别是作用于 flex 容器上的和作用于 flex 项目上的。

flex 容器

能作用到 flex 容器上的样式有这么几个:flex-directionflex-wrapflex-flowjustify-contentalign-itemsalign-content。看到这么几个东西,别被它们吓坏了,多读几遍你就能猜个八九不离十它们是干嘛用的了。下面我们一一来介绍这些样式。

flex-direction

相信你也大概知道了这个样式的作用了,对了就是和方向有关的。flex-direction 这个样式就是用来控制 main axis 的方向的,默认值 row,表示水平从左到右。

  • row,默认的属性值,水平方向,从左到右
  • column,垂直方向,从上到下
  • row-reverse,水平方向,从右到左
  • column-reverse,垂直方向,从下到上
1
2
3
4
ul {
display: flex;
flex-direction: row; /* column || row-reverse || column-reverse */
}

来一张图,你就更好理解了:

flex_direction.png

flex-wrap

flex-wrap 规定了 flex 项目在主轴上是按照一行还是多行显示。

  • nowrap,默认属性,单行显示,会尽力的压缩每个 flex 项目直到刚好容下里面的内容,实在压缩不了的时候 flex 项目就可能会溢出容器。
  • wrap,允许多行显示,当一行显示不下的时候,会变成多行显示。
  • wrap-reverse,多行显示,且行的显示顺序是从下到上,即第一行显示在容器的底部。
1
2
3
4
ul {
display: flex;
flex-wrap: nowrap; /* wrap || wrap-reverse */
}

flex_wrap.png

flex-flow

flex-flow 是一个复合属性,是由 flex-directionflex-wrap 组成的属性。如果只定义了一个属性,那么另外一个属性取默认值。且属性书写顺序没有特别要求。

  • row nowrap,这是默认属性值
1
2
3
4
ul {
display: flex;
flex-flow: row wrap;
}

flex_flow.png

justify-content

justify-content 规定了 flex 项目在主轴的对齐方式。比如当 flex-direction 被设置为 column 时,justify-content 定义的是垂直方向上的对齐方式。

  • flex-start, 默认属性值,flex项目将向着主轴起始位置对齐
  • flex-end, flex 项目将向着主轴结束位置对齐
  • center, flex 项目将在主轴上居中对齐
  • space-between, flex 项目将在主轴上以相同的间距贴着轴的两端对齐
  • space-around, flex 项目将在主轴上以相同的间距靠着两端对齐,且第一个头尾项目和轴的两端之间存在间距,间距是两个项目间距的一半
1
2
3
4
ul {
display: flex;
justify-content: center;
}

justify_content.png

align-items

居然有主轴上的对齐方式,那么肯定也有相关的属性是用来定义交叉轴上的对齐规则的。和 justify-content 一样,align-items 也有 5 个属性定义,其中 flex-startflex-endcenter 是一样的,就不多介绍了。来说说两个不同的:

  • stretch,默认属性值,flex 项目在交叉轴上的尺寸如果没有指定或者是被设置为 auto,那么它将在这个方向上尽量延伸,直到靠着容器边界,但是同时延伸的程度也会受到 max-height 或者 max-width 的影响
  • baselineflex项目在交叉轴上的对齐方式将是由每个项目内容的基线决定
1
2
3
4
ul {
display: flex;
align-items: flex-start;
}

align_items.png

align-content

理解了 justify-contentalign-items 的对齐方式,再来看 align-content 就容易理解多了。它只作用于容器,且只能是存在多个行的容器。注意这里的行是相对于交叉轴来说的。属性值有 6 个:flex-startflex-endcenterstretchspace-betweenspace-around,这些对齐方式上面都介绍过了,大同小异。其中默认值是stretch。结合下图来加深理解:

1
2
3
4
5
ul {
display: flex;
flex-wrap: wrap;
align-content: space-around;
}

align_content.png

flex 项目

上面介绍了定义在 flex 容器上的 css 属性,规范了整个容器里所有项目的全局呈现。这样不够灵活多变,不足以表现某些需要特别显示的项目,所以针对这一现状,w3c 社区又推出了一套作用于 flex 项目上的 css 属性。他们分别是:align-selforderflex-growflex-shrinkflex-basisflexcss 属性。

  • align-self

align-self 规定了单个 flex 项目在交叉轴上的对齐方式,属性值可以是下面一个:flex-startflex-endcenterstretchbaselineauto,其中 auto 为默认属性值,如果被设置为了 auto,那么该 flex 项目最终的对齐方式将是由容器的 align-items 决定。

1
2
3
4
5
6
ul {
display: flex;
}
ul li {
align-self: center;
}

align_self.png

order

order 定义了 flex 项目在容器里的排列顺序。取值可以是负整数、0、正整数,默认取值是 0。数值越大越靠近轴向的末端,数值相同则按照 html 里的顺序排列。

1
2
3
4
5
6
ul {
display: flex;
}
ul li {
order: 2;
}

order.png

flex-grow

flex-grow 规定了 flex 项目的伸展性,其值只能是 0 或者正整数,默认值是 0。如果一个 flex 项目同时设置了width 和值为正整数的 flex-grow 属性,则 width 属性将失效。取值如果是 0 表示不进行伸展;如果是正整数,则会进行伸展,且伸展的尺寸将和数值的大小有关,值越大,伸展得越大。伸展的具体计算数值是该项目占所有可伸展项目总和的比与这些所有可伸展项目占的尺寸的乘积。

flex_grow.png

flex-shrink

与伸展相对应的属性是 flex-shrink,定义了项目的收缩性,值也只能是 0 或者正整数,默认值是 1。如果是 0 表示不进行收缩,如果是正整数则表示进行收缩。如果一个项目同时显示设置了尺寸和收缩值为 1,那么该项目将进行收缩,定义的尺寸将失效。
项目能够进行收缩的前提是必须产生溢出,即所有项目所占尺寸之和必须大于容器尺寸。这个时候容器里所有可收缩的项目就需要通过收缩来消化掉这部分溢出的尺寸。而每个项目具体的收缩量则由其设置的收缩比例决定,数值越大,收缩得越厉害。比如一个容器的尺寸是 400px,只有 2 个项目且尺寸都是 300px,收缩比例是 13,那么容器将溢出 200px,所以第一个项目需要收缩 50px,第二个项目需要收缩 150px,那么收缩完成后它们占据的尺寸分别是 250px150px

flex_shrink.png

flex-basis

flex-basis 定义了项目在伸缩之前的初始尺寸,可以是长度设置(pxremem 等);可以是用百分比基于父级来计算尺寸;也可以是默认的 auto,表示其尺寸由内容决定。除了 auto 外,如果尺寸溢出容器了,那么设置了 flex-basis 的项目间,则会根据每项设置的基准值,按比率伸缩剩余空间。

flex_basis.png

flex

flex 是一个复合属性,是由flex-growflex-shrinkflex-basis 组成的。

  • flex-grow ,用来指定扩展比率,在 flex 属性中该值如果被省略则默认为 1
  • flex-shrink,用来指定收缩比率,在收缩的时候收缩比率会以伸缩基准值加权,在 flex 属性中该值如果被省略则默认为 1
  • flex-basis,用来指定伸缩基准值,即在根据伸缩比率计算出剩余空间的分布之前,表示尺寸的起始数值。在 flex 属性中该值如果被省略则默认为 0%。在 flex 属性中该值如果被指定为 auto,则伸缩基准值的计算值是自身的 width 设置,如果自身的宽度没有定义,则长度取决于内容。

一些缩写说明:

  • flex: 1, 则其计算值为 1 1 0%
  • flex: auto, 则其计算值为 1 1 auto
  • flex: none, 则其计算值为 0 0 auto
  • flex: 0 auto 或者 flex: initial, 则其计算值为 0 1 auto

flex.png

兼容性

flex 布局在现代浏览器中兼容性还是比较令人满意的。可以去 caniuse 里看看,或者直接看这个用 flex 布局写的案例 catty-music

caniuse.png