Flexbox 对你说爱不完

Flexbox 意为弹性布局,是一种新的CSS 3 布局方式,与传统布局方式(基于盒模型,依赖display属性 +position属性 +float属性)相比,flex布局更加灵活,具有响应式,可以解决在布局上的很多麻烦。

废话就不多说了,下面我将尽可能地用简洁明了的言语来描述 Flex 布局。

基本概念

使用了flex布局,则有flex容器(flex container),子元素为项目(flex item)。

在 flex 容器中默认存在两条轴,水平主轴(main axis) 和垂直的交叉轴(cross axis),start和end表示对应轴的起始位置,这是默认的设置,当然你可以通过修改使垂直方向变为主轴,水平方向变为交叉轴。比如将Flexbox的方向设置为row,则主轴就是横轴,而交叉轴就是纵轴;反之设置成column,则主轴就是纵轴,而交叉轴就是横轴,这个下面会具体讲。

每个项目(flex item)占据的主轴空间为 (main size), 占据的交叉轴的空间为 (cross size)。

这里还需要注意的是,不能直截了当地认为宽度就是 main size,高度就是 cross size,这个还要取决于你主轴的方向,如果你垂直方向是主轴,那么项目的高度就是 main size。

实际上,要实现 flex 布局需要先指定一个容器,任何一个容器都可以被指定为 flex 布局,这样容器内部的元素就可以使用 flex 来进行布局。语法如下:

1
2
3
.container {
display: flex | inline-flex; //可以有两种取值
}

给div这类块元素设置display: flex或者给span这类行内元素设display: inline-flex,flex布局即创建!

而Flex布局相关属性正好分为两拨,一拨作用在flex容器上,还有一拨作用在flex子项上。

需要注意的是:当时设置 flex 布局之后,子元素的 floatclearvertical-align 的属性将会失效。

Flex容器上的属性

有下面六种属性可以设置在容器上,它们分别是:

  1. flex-direction
  2. flex-wrap
  3. flex-flow
  4. justify-content
  5. align-items
  6. align-content

1. flex-direction: 决定主轴的方向(即项目的排列方向)

1
2
3
.container {
flex-direction: row | row-reverse | column | column-reverse;
}
  • row(默认):主轴为水平方向,起点在左端

  • row-reverse:主轴为水平方向,起点在右端

  • column:主轴为垂直方向,起点在上沿

  • column-reverse:主轴为垂直方向,起点在下沿

2. flex-wrap: 决定容器内项目是否可换行

默认情况下,项目都排在主轴线上,使用 flex-wrap 可实现项目的换行。

1
2
3
.container {
flex-wrap: nowrap | wrap | wrap-reverse;
}
  • nowrap(默认):不换行,即当主轴尺寸固定时,当空间不足时,项目尺寸会随之调整而并不会挤到下一行

  • wrap:项目主轴总尺寸超出容器时换行,第一行在上方

  • wrap-reverse:换行并反向,第一行在下方

3. flex-flow: flex-direction 和 flex-wrap 的复合简写形式

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

默认值为: row nowrap,这个属性其实没多大卵用,不就是两个属性的缩写嘛。

4. justify-content:定义项目在主轴的对齐方式

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

建立在主轴为水平方向时的测试,即 flex-direction: row

  • flex-start(默认):左对齐

  • flex-end:右对齐

  • center:居中

  • space-between:两端对齐,项目之间的间隔相等,即剩余空间等分成间隙

  • space-around:每个项目两侧的间隔相等,所以项目之间的间隔是项目与边缘的间隔的两倍

5. align-items: 定义项目在交叉轴上的对齐方式

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

建立在主轴为水平方向时的测试,即 flex-direction: row

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

假设容器高度设置为 50px,而项目都没有设置高度或设为auto的情况下,则项目的高度也为 50px

  • flex-start:交叉轴的起点对齐

  • flex-end:交叉轴的终点对齐

  • center:交叉轴的中点对齐

  • baseline: 项目的第一行文字的基线对齐

以文字的底部为主

6. align-content: 定义多根轴线的对齐方式,如果项目只有一根轴线,那么该属性将不起作用

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

什么叫项目只有一根轴线呢?其实可以这么理解:

当你 flex-wrap 设置为 nowrap 的时候,容器仅存在一根轴线,因为项目不会换行,就不会产生多条轴线。

当你 flex-wrap 设置为 wrap 的时候,容器可能会出现多条轴线,这时候你就需要去设置多条轴线之间的对齐方式了。

建立在主轴为水平方向时测试,即 flex-direction: row, flex-wrap: wrap

  • stretch(默认):轴线占满整个交叉轴

  • flex-start:轴线全部与交叉轴上的起点对齐

  • flex-end:轴线全部与交叉轴上的终点对齐

  • center:轴线全部在交叉轴上的中间对齐

  • space-between:轴线与交叉轴两端对齐,轴线之间的间隔平均分布

  • space-around:每个轴线两侧的间隔都相等,所以轴线之间的间隔是轴线与边缘的间隔的两倍

到这里关于容器上的所有属性都讲完了,接下来就来讲讲关于在 flex item(项目) 上的属性。

Flex 项目上的属性

item 项目上有六种属性可运用,它们分别是:

  1. order
  2. flex-grow
  3. flex-shrink
  4. flex-basis
  5. flex
  6. align-self

1. order: 定义项目在容器中的排列顺序,数值越小,排列越靠前,默认值为 0

1
2
3
.item {
order: <integer>;
}

2. flex-grow: 定义项目的放大比例

1
2
3
.item {
flex-grow: <number>;
}

默认值为 0,即如果存在剩余空间,也不放大。

如果所有项目的 flex-grow 属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的 flex-grow 属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。

3. flex-shrink: 定义项目的缩小比例

1
2
3
.item {
flex-shrink: <number>;
}

flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。

如果所有项目的 flex-shrink 属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink 属性为0,其他项目都为1,则空间不足时,前者不缩小。

负值对该属性无效。

4. flex-basis: 定义了在分配容器剩余空间之前项目的默认大小。相当于对浏览器提前告知:浏览器兄弟,我要占据这么大的空间,提前帮我预留好

1
2
3
.item {
flex-basis: <length> | auto;
}

默认值:auto,即项目本来的大小, 这时候 item 项目的宽高取决于 widthheight 的值。

当主轴为水平方向的时候,同时设置 widthflex-basis,会忽略 width。flex顾名思义就是弹性的意思,因此,实际上不建议对flex项目使用 width 属性,因为不够弹性。

当容器剩余空间不足的时候,flex子项目的实际宽度通常不是设置的 flex-basis 尺寸,因为flex布局剩余空间不足的时候默认会收缩,如果有3个子项目,则默认按1:1:1收缩。

5. flex: flex-grow, flex-shrink 和 flex-basis的复合缩写

1
2
3
.item{
flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
}

flex 的默认值是以上三个属性值的组合。假设以上三个属性同样取默认值,则 flex 的默认值为0 1 auto

有关快捷值:

1
2
flex: auto  //等同于flex:1 1 auto
flex: none //等同于flex:0 0 auto

6. align-self: 控制单独某一个项目的垂直对齐方式,与align-items属性语法区别不大

1
2
3
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}

唯一区别就是align-self多了个auto(默认值),表示继承自flex容器的align-items属性值,如果没有父元素,则等同于 stretch

align-items 其他属性值含义一样,只不过 align-self 是对单个项目生效的,而 align-items 则是对容器下的所有项目生效的。

从垂直居中看出flex的强大

以往让元素垂直居中并不容易,直到CSS3的出现,使用绝对定位配合translate属性才让垂直居中变得简单,不过还有一个更爽的办法,那就是使用flex,让垂直居中变得异常简单

1
2
3
4
5
<div class=“wrapper”>
<div class=“div”>
flexbox 对你说爱不完
</div>
</div>

几行简单代码,即可让div垂直居中

1
2
3
4
5
.wrapper {
display: flex;
align-items: center;
justify-content: center;
}

这里最重要的就是包裹元素的三个关键属性:

  • display: flex 将容器指定为flex布局,任何一个元素都可以指定
  • align-items: center 沿交叉轴对齐项目,这里指的是垂直方向
  • justify-content: center 设置主轴内容对齐方式

其他Flex知识点

  • 在Flex布局中,再强调一遍flex子元素中设置floatclear以及vertical-align属性都是没有用的。
  • Flexbox布局最适合应用程序的组件和小规模布局(一维布局),而Grid布局则适用于更大规模的布局(二维布局),有关Grid布局的文章后面会补充。
  • 已经9102年了,Flex老语法不用在管了,果断放弃,然后私有前缀也不用再加了,看到就烦。
  • 如果想更好地理解Flex的工作原理,可以在此页面上尝试flex 布局编辑器

如果觉得文章对你有些许帮助,欢迎在我的GitHub博客点赞和关注,感激不尽!