Flexbox

Posted by Youzi Blog on January 10, 2019

弹性布局

本篇主要记录 CSS3 的一种布局模式 Flexbox,称为弹性盒子,是一种适应不同屏幕大小及设备类型的布局方式。现已被主流浏览器新版本兼容。附上阮一峰的 flex 布局教程http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

内容

弹性盒子由弹性容器(flex container)和弹性子元素(flex item)组成;

设置容器display: flex | inline-flex;可以把容器定义成弹性容器;一个容器可以包含一个或多个弹性子元素;和 div 一样,盒子之定义子元素在容器内的布局,不影响外部的渲染。

默认每个容器只有一行,所以子元素在容器内都是一行显示。

实例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.flex-container {
    display: -webkit-flex;
    display: flex;
    width: 400px;
    height: 250px;
    background-color: lightgrey;
}
.flex-item {
    background-color: cornflowerblue;
    width: 100px;
    height: 100px;
    width: inherit;
    margin: 10px;
}

在容器上的属性

flex-direction

属性flex-direction: row | row-reverse | column | column-reverse,望名生义,默认从左向右,反向,从上到下,反向。

flex-wrap

属性flex-wrap: nowrap | wrap | wrap-reverse | initial | inherit;

  • nowrap: 默认容器只有一行,子元素可能会溢出。
  • wrap: 弹性容器为多行,溢出部分会放到下一行,子元素内部会发生断行。
  • wrap-reverse:反转 wrap
flex-flow

属性flex-flow: flex-direction | flex-wrap是前两个属性的简写。

justify-content

属性justify-content: flex-start | flex-end | center | space-between | space-around;,这个属性是定义子元素的水平对齐方式

  • flex-start: 默认值,水平左对齐;
  • flex-end: 水平右对齐
  • center: 水平居中,如果溢出,会在水平方向上两边溢出
  • space-between: 平均分布,如果剩余空间为负或者只有一个子元素,则等同于flex-start;第一个和最后一个子元素对齐容器两边界。
  • space-around: 平均分布,第一个和最后一个子元素距离边界有一半的间隔。如果剩余空间为负或只有一个子元素,则等同于 center。
align-items

属性align-items: flex-start | flex-end | center | baseline | stretch;,定义在垂直方向上子元素的对齐方式;

  • flex-start: 上对齐
  • flex-end: 下对齐
  • center: 居中对齐,溢出时向两端延伸
  • baseline: 子元素中第一行文字的基线对齐
  • stretch: 默认值,如果子元素未设置高度或高度是 auto,则将占满整个容器高度
align-content

属性align-content: flex-start | flex-end | center | space-between | space-around | stretch,定义轴线的对齐方式,如果只有一根轴,属性不起作用

  • flex-start: 多行上对齐
  • flex-end: 多行下对齐
  • center: 多行居中对齐
  • space-between: 多行两端对齐,间隔平均分布
  • space-around: 多行两端对齐,第一行和最后一行也有间隔
  • stretch: 默认,充满

子元素的属性

order

属性order: int;,定义子元素的排列顺序,数值越小,排列越靠前,默认值是 0;

flex-grow

属性flex-grow: int;,定义子元素放大比例,默认为 0,即如果存在剩余空间也不放大;

实例:所有子元素都设为 1,则会平均分配剩余空间,如果有一个设为 2,则这个元素占据的剩余空间会比其他多一倍;

flex-shrink

属性flex-shrink: int;,定义缩小比例,默认 1,即空间不足时,该子元素会缩小;

实例:如果所有子元素设为 1,有一个项目为 0,当空间不足时,这个元素不会缩小。

flex-basis

属性flex-basis: length | auto;,定义子元素占据的固定空间。可以设为和宽高一样的值;设为 auto 时是项目本来的大小(实际内容的大小,或是 width 的值)

flex

是前 3 个的简写,默认值是前面的默认值,分别是 0,1,auto,后面两个是可选的;

  • flex: 0; = flex: 0 1 0%;表示该子元素会缩小自己,来提供给其他空间,即只占用自己实际内容的空间,即使设置了 width 也没用,前提是其他元素设置了flex-grow: >0
  • flex:1; = flex: 1 1 0%;表示子元素会放大自己,也会缩小自己,根据其他元素的设置;
  • flex: auto; = flex: 1 1 auto;缩放,如果这个子元素设置了 width,则计算剩余空间时,先去掉固定宽度这部分,剩下的空间是剩余空间;
  • flex: none; = flex: 0 0 auto;表示该子元素不占用其他剩余空间,就占着自己的;
  • flex: initial; = flex: 0 1 auto;缩小,和flex: 0;的区别就是 width 会起作用,会保持元素自身设置的最小宽度。
align-self

定义单个子元素的垂直对齐方式。贴个实例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
.flex-container {
display: -webkit-flex;
display: flex;
width: 400px;
height: 250px;
background-color: lightgrey;
}

.flex-item {
background-color: cornflowerblue;
width: 60px;
min-height: 100px;
margin: 10px;
}

.item1 {
-webkit-align-self: flex-start;
align-self: flex-start;
}
.item2 {
-webkit-align-self: flex-end;
align-self: flex-end;
}

.item3 {
-webkit-align-self: center;
align-self: center;
}

.item4 {
-webkit-align-self: baseline;
align-self: baseline;
}

.item5 {
-webkit-align-self: stretch;
align-self: stretch;
}

水平垂直居中

一个基于 flex 布局的解决方案:

1
2
3
4
5
6
7
8
9
10
11
12
13
.flex-container {
    display: -webkit-flex;
    display: flex;
    width: 400px;
    height: 250px;
    background-color: lightgrey;
}
.flex-item {
    background-color: cornflowerblue;
    width: 75px;
    height: 75px;
    margin: auto;
}

flexbox 实现圣杯布局

关于圣杯布局:

  • headerfooter定高,宽度拉满;
  • content是中间部分,是一个三栏布局;
  • 三栏布局navaside定宽;
  • 三栏布局main优先渲染,自适应宽度。

DOM:

1
2
3
4
5
6
7
8
9
<body>
  <header>head</header>
  <div class="content">
    <main>main</main>
    <nav>nav</nav>
    <aside>aside</aside>
  </div>
  <footer>foot</footer>
</body>

style:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<style type="text/css">
html,
body {
  /*注意这里有html标签,这样会有最小高度的限制,不然缩放时高度不会有600px*/
  display: flex;
  flex-direction: column;
  min-height: 600px;
  height: 100%;
}
header,
footer {
  /*固定头尾高度*/
  height: 150px;
  background-color: #666;
  /*flex: none; = flex: 0 0 auto;头尾不会随视窗放大和缩小*/
  flex: none;
}
.content {
  /*注意这是三栏布局的容器,所以要设置display: flex;*/
  flex: 1;
  display: flex;
}
nav,
aside {
  background-color: #eb6f43;
  /*不随视窗放大而放大,但会随着缩小,初始的宽度是200px*/
  flex: 0 1 200px;
}
main {
  background-color: #d6d6d6;
  flex: 1;
}
nav {
  /*设置排列顺序,另外两个是0,这个是-1,所以在main前面*/
  order: -1;
}
</style>

总结一下圣杯布局,容器设置 flex 布局并且设定高度,设置头尾定高,content 填充剩余空间;content 也需要设置 flex 布局,nav 和 aside 设置定宽且不放大,main 设置自适应,nav 设置 order 排列顺序为第一个。

使用中的总结

  • flex-direction: column;时,框体的宽度会自动撑满整个容器;
  • 容器设置成display: flex;,不会对子元素中的子元素产生影响;

自动填充弹性容器

一个骚操作,首先要固定容器的高度和宽度,然后对子元素设置高度宽度为继承,这样就能让子元素自动填充容器了;

实际应用中发现,如果想设置某个子元素为固定宽度,在某个范围内是可以设置成功的,但是超过这个范围就会被压缩,没有设置定宽的子元素会平摊剩下的空间(设置了继承的情况下);不设置继承的话,子元素宽度会随着子元素的内容自适应。

2020.03.31 更新,内容高度撑开的问题

最近刚好在做小程序的时候,在动态渲染元素时,出现了flex布局错乱的情况,记录一下;

首先容器container设置成display: flex;,并且规定了容器的高度height: 100%;,此时如果只是静态页面,布局样式没问题,这里指的是container的子元素box1高度会随着box1的子元素box2内容的高度而变化,有点绕,其实就是flex布局的子元素高度是根据其内容来确定的;

而在动态渲染一些节点(这些节点只是box1的兄弟元素)的时候发现,容器的子元素box1高度变成0了,导致布局错误,搜了一些发现在这篇博客里Flex布局高度撑开不足问题,提到了这个问题,所以就在box1元素的外层,又添加了一层容器,问题就解决了。