弹性布局
本篇主要记录 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 实现圣杯布局
关于圣杯布局:
header
和footer
定高,宽度拉满;content
是中间部分,是一个三栏布局;- 三栏布局
nav
和aside
定宽; - 三栏布局
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
元素的外层,又添加了一层容器,问题就解决了。