传统的响应式布局方式,通过position:absoulte和float
<main>
<nav>1</nav>
<article>2</article>
</main>
<style>
* {
padding: 0;
margin: 0;
}
// 父元素相对定位
main {
position: relative;
height: 100vh;
}
// 子元素绝对定位
nav {
width: 80px;
position: absolute;
top: 0;
left: 0;
bottom: 0;
background: linear-gradient(45deg,red,greenyellow);
}
// 另一个资源通过剩余宽度自适应
article {
background: linear-gradient(90deg,gray,greenyellow);
margin-left: 90px;
height: 100vh;
}
</style>
弹性布局:
* {
padding: 0;
margin: 0;
}
main {
display: flex;
height: 100vh;
}
nav {
width: 80px;
background: linear-gradient(45deg,red,greenyellow);
}
article {
background: linear-gradient(90deg,gray,greenyellow);
flex: 1;
}
可以看出仅少量的代码就可以实现响应式布局,相比于传统的响应式布局方式方便许多。同时当页面增加元素的时候,会自适应布局,而不需要再改变代码。
1. 弹性盒子声明
如果某元素声明为弹性盒子display:flex
,那么该元素内部的子元素的布局方式则由父元素弹性盒子的规则来定义。
弹性盒子有两种:块级弹性盒子、行内块级弹性盒子
-
块级弹性盒子
display: flex;
声明为此方式的盒子表现为块级元素的特性。
-
行内块级弹性盒子
diplay: inline-flex;
声明此方式的盒子表现为行内块级元素的特性。
2. 弹性盒子规则
弹性盒子中的内容称为元素。在弹性盒子上定义规则,会影响弹性盒子中元素的布局方式。以下的规则都是在弹性盒子上进行制定。(原因:影响所有的元素,而不是单个元素)
2.1 弹性元素布局方式
通过flex-direction
设置弹性盒子中元素的布局方式。也即安排元素是从上往下,还是从左到右开始放置。
值 | 说明 |
---|---|
row | 从左到右水平排列元素(默认值) |
row-reverse | 从右向左排列元素 |
column | 从上到下垂直排列元素 |
column-reverse | 从下到上垂直排列元素 |
例子:
flex-direction: row-reverse;
2.2 弹性元素溢出处理
当一行/一列的元素过多,不能显示完全。
此时弹性盒子有两种方式安排元素的布局:
- 改变元素宽/高尺寸自适应盒子的变化(默认的情况)
- 通过属性设置元素换行处理(
flex-wrap
)
如果没有设置flex-wrap
,则元素溢出的处理则是采用默认方式,也即改变元素本身的尺寸。
如果设置了flex-wrap
,则按照属性值换行处理
选项 | 说明 |
---|---|
nowrap | 元素不拆行或不拆列(默认值) |
wrap | 容器元素在必要的时候拆行或拆列。 |
wrap-reverse | 容器元素在必要的时候拆行或拆列,但是以相反的顺序 |
如果盒子的布局方式为row
,那么换行时,元素所转换到的那行则在当前行的下面。
也即:flex-wrap会根据横轴(flex-direction设置的布局方式)决定新行的堆叠方向。
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap;
此时结果为:
当flex-wrap:wrap-reverse
时,反方向换行。默认情况下新行都是在原来所处行下方,则此属性则规定新行在原来所处行的上方。注意:则属性只是规定在原来行上方/下方新建一行来放置溢出的元素,而元素在新行上的布局仍然是由flex-direction
来控制
display: flex;
flex-direction: row-reverse;
flex-wrap: wrap-reverse;
结果为:
2.3 flex-direction和flex-wrap的组合写法
flex-flow
是flex-direction
和flex-wrap
的组合写法,不考虑顺序。
flex-flow: wrap-reverse row-reverse;
2.4 主轴和交叉轴
- 主轴:元素布局的方向也就是主轴的方向
flex-direction: row;
flex-direction: row-reverse;
-
交叉轴:属性
flex-wrap
指定元素溢出时新建行是从上到下/从下到上,还是从左到右/从右到左flex-wrap: wrap;
flex-wrap: wrap-reverse;
-
练习
flex-flow: column-reverse wrap-reverse;
2.5 主轴对齐方式
flex-direction
规定了元素的排列方向,也即从上往下开始放置元素/从左往右开始放置元素。但是这个属性没有规定元素放置的位置,也即排列方式。
justify-content
,则用于规定元素的主轴上的排列方式,也即平均放置在主轴上,还是从左开始放置,还是从右开始放置。
因此,可以通过flex-direction
规定元素排列方向,justify-content
规定元素排列方式。
属性值 | 说明 |
---|---|
flex-start | 元素对齐主轴起点 |
flex-end | 元素对齐主轴终点 |
center | 元素对齐弹性容器中心 |
space-between | 第一个元素紧靠起点,最后一个元素紧靠终点,余下元素平均分配空间 |
space-around | 每个元素两侧的间隔相等。所以,元素之间的间隔比元素与容器的边距的间隔大一倍 |
space-evenly | 元素间距离平均分配 |
flex-direction: row;
justify-content: flex-end;
flex-direction: row;
justify-content: center;
flex-direction: row;
justify-content: space-between;
flex-direction: row-reverse;
justify-content: space-around;
flex-direction: row-reverse;
justify-content: space-evenly;
2.6 交叉轴对齐方式
当弹性盒子放不下元素时,且允许换行,此时换行可能会导致交叉轴上有多行元素存在。
此时可以对交叉轴上的单行元素在交叉轴方向规定显示位置,或者对交叉轴上的行与行之间(多行元素)规定显示位置。
-
规定交叉轴上单行元素的显示位置
align-items
属性值 说明 stretch 元素被拉伸以适应容器(默认值)(当不设置元素在交叉轴方向上的长度时) center 元素位于容器的中心 flex-start 元素位于容器的交叉轴开头 flex-end 元素位于容器的交叉轴结尾 假设弹性盒子默认规则为:
display: flex; flex-direction: row;
基于以上规则进一步讨论align-items
属性
假设元素不设置高度,那么弹性盒子默认规定元素align-items
属性值为stretch
,表现为元素被拉伸以适应容器。
align-items: stretch;
如果设置了高度,那么该属性就不起作用了。
align-items: flex-start;
表明单行元素紧靠交叉轴起点
align-items: center
表明单行元素位于交叉轴中心
-
规定交叉轴上多行元素之间的显示方式
align-content
,用法与justify-content
一样。属性值 说明 stretch 拉伸元素,使其平均分配空间(默认值),但是需要在不设置元素在交叉轴上的长度才有效。 flex-start 所有行紧靠交叉轴起点 flex-end 所以行紧靠交叉轴终点 center 所有行对齐于交叉轴中心 space-between 第一行紧靠起点,最后一行紧靠终点,余下行元素平均分配空间 space-around 每一行两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍 space-evenly 行间距离平均分配 -
假设弹性盒子默认规则为:
display: flex; flex-direction: row; flex-wrap: wrap;
基于以上规则进一步讨论
align-content
属性align-content: flex-start;
所以行紧靠交叉轴起点
-
align-content: space-evenly
行之间平分空间
注意:设置了align-content会覆盖align-items的设置
3. 弹性元素规则
弹性元素规则定义单个元素在弹性盒子中的显示方式。
3.1 弹性元素在交叉轴上的排列方式
align-self
元素可以控制单个元素在交叉轴上的排列方式。不同于align-items
是控制一行元素整体在交叉轴上的排列方式。
属性值 | 说明 |
---|---|
stretch | 将空间平均分配给元素 |
flex-start | 元素紧靠主轴起点 |
flex-end | 元素紧靠主轴终点 |
center | 元素从弹性容器中心开始 |
用法与align-items
一样。
div:nth-of-type(1) {
align-self: flex-end;
}
3.2 主轴上可用空间分配
弹性元素在主轴上可以对可用空间进行分配。
flex-grow
属性值为数值,表示可用空间分为几等份,以及当前元素所占的比例。可以为整数/小数
计算公式
当前元素所分配的剩余可用空间 = (剩余空间 / 划分等份)* 当前元素所占份数
实际元素所占空间 = 原来的空间 + 当前元素所分配的剩余可用空间
如果没有设置缩放比例,那么默认为0;
<main>
<div>1</div>
<div>2</div>
<div>3</div>
</main>
<style>
main {
display: flex;
width: 600px;
height: 200px;
margin: 10px auto;
border: 1px solid red;
flex-flow: row wrap;
}
div {
width: 100px;
height: 60px;
padding: 10px;
// 使得元素的高和宽限于边框内
box-sizing: border-box;
background-clip: content-box;
background-image: linear-gradient(to top,pink,palegoldenrod);
flex-grow: 1;
}
// 设置元素所占可用空间的比例
div:nth-of-type(1) {
flex-grow: 1;
}
div:nth-of-type(2) {
flex-grow: 2;
}
div:nth-of-type(3) {
flex-grow: 0;
}
</style>
注意:该属性是弹性元素在主轴上可用空间的划分。
使用场景:弹性布局,头部 主体 尾部 通过此属性实现弹性布局。
3.3 主轴上不足空间时元素缩放
当在主轴方向上元素所占空间大于弹性盒子在主轴上的空间的时候,如果没有设置flex-wrap
换行处理。那么默认会进行缩放。且每个元素缩放比例默认是一样的。
flex-shrink
可以设置每个元素的缩放比例。
<main>
<div>1</div>
<div>2</div>
<div>3</div>
</main>
<style>
main {
display: flex;
width: 500px;
height: 200px;
margin: 10px auto;
border: 1px solid red;
flex-flow: row;
}
div {
width: 200px;
height: 60px;
padding: 10px;
// 使原来宽高固定在边框内
box-sizing: border-box;
background-clip: content-box;
background-image: linear-gradient(to top,pink,palegoldenrod);
flex-grow: 1;
}
// 设置缩放比例
div:nth-of-type(1) {
flex-shrink: 0;
}
div:nth-of-type(2) {
flex-shrink: 1;
}
div:nth-of-type(3) {
flex-shrink: 3;
}
</style>
3.4 主轴的基准尺寸定义
flex-basis
属性定义了在分配多余空间之前,元素占据的主轴空间。浏览器会根据这个属性计算主轴上是否有多余的空间。类似于width
height
以及max/min-height
max/min-width
但是存在一定的优先级的问题。
max/min-width/height
> flex-basis
> width/height
也即如果设置了flex-basis
,则width/height
是无效的
单位: px/百分比
3.5 flex-组合写法
flex
是flex-grow
flex-shrink
flex-basis
组合写法
顺序为: flex-grow
flex-shrink
如果只写一个数值,则表示缩放,缩小都为此比例。
3.6 控制弹性元素位置
在主轴上面可以通过flex-direction
规定弹性元素整体排列方向,通过justify-content
规定元素排列方式,通过flex-grow
规定元素对可用空间的分配,通过flex-shrink
规定元素在空间不足的时候的缩放比例,通过flex-basis
设定元素的基准尺寸。但是以上这些属性都是在元素原来放置顺序上进行的一系列的操作,并不能单独控制元素之间互相交换位置。
order
用于控制弹性元素的位置,默认为0,数值越小越在前面(前与后是相对于主轴的方向的),可以是负数或者整数。
默认值:order: 0
表示所有元素都按照原来的顺序进行放置,没有优先级之分。
div:nth-of-type(1) {
order: 1;
}
设置第一个元素的order: 1
,由于数值越大越在后面,所以第一个元素放置在主轴的结束处。
4. 弹性文本
弹性盒子中的元素不仅可以包含标签节点,也可以操作文本节点
<main>
1 // 文本节点
<div>div盒子</div>
3 // 文本节点
</main>
<style>
main {
display: flex;
width: 300px;
height: 200px;
margin: 10px auto;
border: 1px solid red;
flex-flow: row;
justify-content: space-between;
}
div {
width: 60px;
height: 60px;
background: linear-gradient(45deg,pink,deeppink);
}
</style>
5. 定位属性应用于弹性元素
在弹性元素上应用定位属性,那么弹性布局的规则不再适用于添加了定位的元素。
因此:添加定位属性的弹性元素不参与弹性布局。
6. 自动空间
在弹性布局中对元素使用margin-right
等属性可以自动撑满空间(当前元素把剩余空间撑开,使得其元素右边相邻的元素紧靠有边界,且当前元素中子元素的增加不会影响整体的布局效果)。
以上为一种方式可以自动分配剩余空间,也可以通过弹性盒子主轴上的规则来进行布局也行。