# Flex 弹性布局从入门到实践
TIP
传统的浮动+定位布局兼容性好,但布局繁琐,在移动端应用起来相对麻烦。而我们今天要学习的 Flex 弹性布局,操作方便,布局极为简单,在移动端应用很广泛。
当然,他的应用不仅限于移动,PC 端同样适用。
# 一、Flex 布局的基本概念
TIP
接下来让我们一起来学习 Flex 弹性布局,首先我们来了解下 lex 布局相关的一些基本概念
- 什么是 Flex 布局
- 什么是 Flex 容器(
Flex container
) 和 Flex 项目(Flex item
) - 什么是主轴,什么是交叉轴
- Flex 项目的默认表现形式
# 1、什么是 Flex 布局
TIP
Flex
是Flexible Box
的缩写,意为“弹性盒子”。Flex
布局是一种一维的布局模型,它给flexbox
的子元素之间提供了强大的空间分布和对齐能力我们说
flexbox
是一种一维的布局,是因为一个flexbox
一次只能处理一个维度上的元素布局,一行或者一列
# 2、什么是 Flex 容器(Flex container)和 Flex 项目(Flex item)
TIP
- 采用Flex 布局的元素,称为 Flex 容器(
flex container
),简称“容器”。 - 它的所有直接子元素自动成为容器成员,称为 Flex 项目(
flex item
),简称“项目”。- 通过给元素添加
display:flex;
或display:inline-flex;
来指定元素为 Flex 布局容器display:flex;
弹性布局,元素自身以块级元素显示display:inline-flex;
弹性布局,元素自身以行内块元素呈现
- 通过给元素添加
- 任何一个元素都可以指定为 Flex 布局
- Flex 布局,项目(子元素)的
float
、clear
和vertical-align
属性将失效。
以下代码中
.flex-container
盒子为 Flex 容器 ,里面的子元素.flex-item
为 Flex 项目
<style>
.flex-container {
/* 布局方式:弹性布局 ,元素自身以块级元素显示 */
display: flex;
/* 布局方式:弹性布局,元素自身以行内块元素呈现 */
display: inline-flex;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
</div>
</body>
inline-flex | flex |
---|---|
# 3、什么是主轴,什么是交叉轴
TIP
- Flex 容器默认存在两根轴:水平的主轴(main axis)和 垂直的交叉轴(cross axis)
- 主轴的开始位置(与边框的交叉点)叫做
main start
,结束位置叫做main end
; - 交叉轴的开始位置叫做
cross start
,结束位置叫做cross end
- Flex 项目默认沿主轴排列,(即 Flex 项目默认从左往右沿水平排列)。
- 单个Flex 项目占据的主轴空间叫做
main size
(主轴尺寸),占据的交叉轴空间叫做cross size
(交叉尺寸)
# 4、Flex 项目的默认表现形式
TIP
当 flex 容器和 flex 项目没有添加任何Flex 容器和Flex 项目相关属性时,flex 项目默认的表现形式如下:
- 子元素(项目)排列为一行 (
flex-direction
属性的初始值是row
)。 - 子元素(项目)从主轴的起始线开始排列
- 子元素(项目)不会在主维度方向拉伸(放的下,不会拉伸),但放不下,会缩小
- 子元素(项目)没有设置高度时,被拉伸来填充交叉轴大小(单行时项目的高度等于容器高)
flex-basis
属性为auto
(即元素的宽为自动)flex-wrap
属性为nowrap
(子项默认放不下时,不会换行)
代码演示
<style>
.flex-container {
padding: 10px;
width: 200px;
height: 200px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
}
.flex-item {
/* 未设置高度 */
width: 100px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
margin: 5px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
</div>
</body>
注:
.flex-item
的宽为 100px,4 个加起来 400px,超过了.flex-container
宽度,但元素并没换行,而是自动压缩到容器中显示。.flex-item
没有设置高度时,其高度会被拉伸与父容器.flex-container
的高一样大小。
# 二、Flex 容器属性
接下来我们来学习 Flex 容器相关的属性,以下 6 个属性都是设置在Flex 容器上
属性名 | 说明 |
---|---|
flex-direction | 设置主轴的方向 |
flex-wrap | 设置(项目)子元素是否换行 |
flex-flow | 复合属性,相当于同时设置了 flex-direction 和 flex-wrap |
justify-content | 设置主轴上的(项目)子元素排列方式 |
align-items | 设置交叉轴上的(项目)子元素排列方式 (单行) |
align-content | 设置多轴线在交叉轴上排列方式 (多行) |
# 1、flex-direction 设置主轴方向
TIP
flex-direction 属性决定了 Flex 容器的主轴方向,即 Flex 项目的排列方向
- 默认主轴方向就是 x 轴,水平向右
- 默认交叉轴就是 y 轴,垂直向下
语法:
/* 主轴为行(x轴),水平向右 */
flex-direction: row;
flex-direction 属性的 4 个值
属性值 | 说明 |
---|---|
row | (默认值)主轴为水平方向,起点在左端。(即:交叉轴在垂直方向,起点在上边框位置 |
row-reverse | 主轴为水平方向,起点在右端。(即:交叉轴在垂直方向,起点在元素上边框位置) |
column | 主轴为垂直方向,起点元素上边框位置。(即:交叉轴为水平方向,起点在左端) |
column-reverse | 主轴为垂直方向,起点在下沿。 (即:交叉轴为水平方向,起点在左端 ) |
案例演示:
<style>
.flex-container {
/* 布局方式:弹性布局,元素自身以行内块元素呈现 */
display: inline-flex;
/* 定义主轴方向,可选值:row、row-reverse、column、column-reverse */
flex-direction: row;
padding: 10px;
background-color: skyblue;
}
.flex-item {
width: 50px;
height: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
margin: 10px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
flex-direction 属性,不同值的表现效果如下:
row | row-reverse | column | column-reverse |
---|---|---|---|
# 2、flex-wrap 项目如何换行
TIP
- 默认情况下,项目都排在一条线(又称 "轴线" )上排列。
flex-wrap
属性定义,如果项目在一条轴线(主轴)排不下时,如何换行。
语法:
/* 放不下时,不换行 */
flex-wrap: nowrap;
flex-wrap 属性的 3 个值
属性值 | 说明 |
---|---|
nowrap | (默认):不换行 |
wrap | 换行,第一行在上方 (或第一列左边) |
wrap-reverse | 换行,第一行在下方(或第一列在右边) |
<style>
.flex-container {
/* 弹性布局 */
display: flex;
/* 主轴为垂直方向 */
/* flex-direction: column; */
/* 项目在放不下时,如何换行 wrap nowrap wrap-reverse */
flex-wrap: wrap;
width: 200px;
height: 200px;
padding: 10px;
background-color: skyblue;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
margin: 5px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
</div>
</body>
主轴为 row,水平方向时
nowrap | wrap | wrap-reverse |
---|---|---|
主轴为 column,垂直方向时
nowrap | wrap | wrap-reverse |
---|---|---|
# 3、flex-flow 主轴方向和项目如何换行
TIP
flex-flow
属性是flex-direction
属性和flex-wrap
属性的简写形式,默认值为row nowrap
。
语法:
flex-flow: row nowrap;
<style>
.flex-container {
width: 100px;
height: 200px;
padding: 10px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
/* flex-wrap 主轴方向和项目如何换行 */
flex-flow: column wrap;
}
.flex-item {
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
margin: 5px;
padding: 5px 10px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
</div>
</body>
row nowrap | row wrap | column nowrap | column wrap |
---|---|---|---|
# 4、justify-content 项目在主轴上对齐方式
TIP
justify-content
属性定义了项目在主轴上的对齐方式
/* 项目在主轴上左对齐 */
justify-content: flex-start;
justify-content 属性的 5 个值
属性值 | 说明 |
---|---|
flex-start | (默认值)左对齐 |
flex-end | 右对齐 |
center | 居中 |
space-between | 两端对齐,项目之间的间隔都相等 |
space-around | 每个项目两侧的间隔相等。所以,项目之间的间隔比项目与边框的间隔大一倍。 |
space-evenly | 使每个元素之间和元素距离边距的距离都相等,但iphone 的 SE 上不支持,会失效,基本不用 |
<style>
.flex-container {
padding: 10px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
/* 项目在主轴上的对齐方式 */
justify-content: center;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
margin: 5px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
</div>
</body>
flex-start | flex-end | center |
---|---|---|
space-between | space-around | space-evenly |
---|---|---|
# 5、align-items 项目在交叉轴上对齐方式
TIP
align-items
属性定义项目在交叉轴上如何对齐,只对单行有效
/* 默认值,项目未设置高度或设为auto,将占满整个容器的高度 */
align-items: stretch;
align-item 属性的 5 个值
属性值 | 说明 |
---|---|
stretch | (默认值):如果项目未设置高度或设为 auto,将占满整个容器的高度。 |
flex-start | 交叉轴的起点对齐 |
flex-end | 交叉轴的终点对齐 |
center | 交叉轴的中点对齐 |
baseline | 所有元素向基线对齐。侧轴起点到元素基线距离最大的元素将会于侧轴起点对齐以确定基线。 |
注意:
align-items
的值不是stretch
时,其项目未设置高时,其高为内容大小,并不会拉伸到容器高度。
<style>
.flex-container {
height: 200px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
/* 项目在交叉轴上如何对齐 */
align-items: baseline;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
padding: 5px 10px;
margin: 0 5px;
}
.flex-item:nth-child(1) {
height: 50px;
font-size: 14px;
}
.flex-item:nth-child(2) {
height: 100px;
font-size: 40px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
stretch | flex-start | flex-end |
---|---|---|
center | baseline |
---|---|
当主轴放不下,允许换行时,align-items 的效果
- 当项目放不下,换行时,可以把每一行看作一个新的 flex 容器
align-items
控制项目在这个新容器的交叉轴上的对齐方式- 每一行容器占的高度 = 当前行最高元素的高 +(容器高 - 每一行最高元素的高) / 行数
案例
<style>
.flex-container {
width: 300px;
height: 300px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
/* 项目在交叉轴上如何对齐 */
align-items: baseline;
/* 放不下换行 */
flex-wrap: wrap;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
padding: 5px 10px;
margin: 0px 5px;
}
.flex-item:nth-child(2) {
height: 100px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
</div>
</body>
stretch | flex-start | flex-end |
---|---|---|
center | baseline |
---|---|
# 6、align-content 多根轴线对齐方式(多行)
TIP
align-content
属性定义了多根轴线在(交叉轴上的)对齐方式。- 如果项目只有一根轴线,该属性不起作用。
/* 多行在交叉轴上居中对齐 */
align-content: center;
align-content 属性的 6 个值
属性值 | 说明 |
---|---|
stretch | (默认值)轴线占满整个交叉轴 |
flex-start | 与交叉轴的起点对齐 |
flex-end | 与交叉轴的终点对齐 |
center | 与交叉轴的中点对齐 |
space-between | 与交叉轴两端对齐,轴线之间的间隔平均分布 |
space-around | 每根轴线两侧的间隔都相等。所以,轴线之间的间隔比轴线与边框的间隔大一倍。 |
<style>
.flex-container {
height: 300px;
width: 300px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
/* 项目放不下自动换行 */
flex-wrap: wrap;
/* 多轴线在交叉轴上的对齐方式 */
align-content: space-around;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
padding: 5px 10px;
margin: 5px;
}
.flex-item:nth-child(1) {
height: 50px;
}
.flex-item:nth-child(2) {
height: 100px;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
<div class="flex-item">6</div>
</div>
</body>
flex-start | flex-end | center |
---|---|---|
stretch | space-between | space-around |
---|---|---|
# 三、Flex 项目属性
TIP
以下 6 大属性为 Flex 项目属性,都是直接添加到项目身上。
属性名 | 说明 |
---|---|
order | 属性定义项目的排列顺序。数值越小,排列越靠前,默认为 0 |
align-self | 单个项目有与其他项目不一样的对齐方式,可覆盖align-items 属性默认值为 auto ,表示继承父元素的align-items 属性,如果没有父元素,则等同于stretch 。 |
flex-grow | flex 项 主尺寸 的 flex 增长系数。默认为0 ,即如果存在剩余空间,也不放大。 |
flex-shrink | flex 项主尺寸的缩小比例,默认为1 ,即如果空间不足,该项目将缩小。 |
flex-basis | 定义了在分配多余空间之前,项目占据的主轴空间(main size ) |
flex | flex 属性是flex-grow , flex-shrink 和 flex-basis 的简写默认值为 0 1 auto 。后两个属性可选。 |
# 1、order 项目的排列顺序
TIP
order
属性定义项目的排列顺序。order
属性值为>0
的整数,数值越小,排列越靠前,默认为 0。
语法:
order: 1;
<style>
.flex-container {
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
padding: 5px 10px;
margin: 5px;
}
.flex-item:nth-child(1) {
/* 排列顺序,数值越小,越排前 */
order: 1;
}
.flex-item:nth-child(2) {
/* 排列顺序,数值越小,越排前 */
order: 3;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
</div>
</body>
# 2、align-self 单个项目交叉轴对齐方式
TIP
align-self
属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items
属性。align-self
的默认值为auto
,表示继承父元素的align-items
属性- 如果父元素没有设置
align-items
属性,则等同于stretch
(要生效,元素自身没有设置高度)。
/* 与交叉轴起点对齐 */
align-self: flex-start;
align-self 属性的 6 个值
该属性的 6 个值,除了 auto,其他都与 align-items 的属性完全一致
属性值 | 说明 |
---|---|
auto | 默认值 表示继承父元素的 align-items 属性,如果没有父元素,则等同于stretch 。 |
stretch | 如果项目未设置高度或设为auto ,将占满整个容器的高度。 |
flex-start | 交叉轴的起点对齐 |
flex-end | 交叉轴的终点对齐 |
center | 交叉轴的中点对齐 |
baseline | 项目的第一行文字的基线对齐 |
<style>
.flex-container {
height: 200px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
align-items: center;
}
.flex-item {
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
padding: 5px 10px;
margin: 5px;
}
.flex-item:nth-child(1) {
align-self: auto;
}
.flex-item:nth-child(2) {
align-self: stretch;
}
.flex-item:nth-child(3) {
align-self: flex-start;
}
.flex-item:nth-child(4) {
align-self: flex-end;
}
.flex-item:nth-child(5) {
align-self: center;
}
.flex-item:nth-child(6) {
align-self: baseline;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">auto</div>
<div class="flex-item">stretch</div>
<div class="flex-item">flex-start</div>
<div class="flex-item">flex-end</div>
<div class="flex-item">center</div>
<div class="flex-item">baseline</div>
</div>
</body>
注意:
当项目换行时,其align-self
单个项目对齐方式,是相对于其所在的那一行的轴线而言。
<style>
.flex-container {
height: 400px;
width: 600px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
/* 允许换行 */
flex-wrap: wrap;
/* 项目在交叉轴,垂直方向上对齐方式 */
align-items: center;
}
.flex-item {
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
background-color: tomato;
padding: 5px 10px;
margin: 5px;
}
.flex-item:nth-child(1) {
/* 单独设置了高为100px */
height: 100px;
align-self: auto;
}
.flex-item:nth-child(2) {
align-self: stretch;
}
.flex-item:nth-child(3) {
align-self: flex-start;
}
.flex-item:nth-child(4) {
align-self: flex-end;
}
.flex-item:nth-child(5) {
align-self: center;
}
.flex-item:nth-child(6) {
align-self: baseline;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">auto</div>
<div class="flex-item">stretch</div>
<div class="flex-item">flex-start</div>
<div class="flex-item">flex-end</div>
<div class="flex-item">center</div>
<div class="flex-item">baseline</div>
</div>
</body>
# 3、flex-grow 项目主轴放大系数
TIP
flex-grow
设置 flex 项目 主尺寸(main size) 的 flex 增长系数- 主尺寸是项目的宽度或高度,这取决于
flex-direction
值 - flex-grow 属性,在 Flex 容器有剩余空间时生效(默认主轴为水平轴)
剩余空间 = flex 容器宽大小 - 所有 flex 项目宽加起来的大小
注:剩余空间的值一定要是大于 0 的
- flex-grow 的默认值为 0,表示及时有剩余空间,也不增长(放大)
- flex-grow 的值为>=0 的数字。
# (1)项目放大后尺寸计算公式
TIP
- 当所有项目的 flex-grow 值的总和加起来
< 1
时项目放大后宽 = 项目原始宽 + 剩余空间 * 项目的 flex-grow 值
- 当所有项目的 flex-grow 值的总和加起来
>= 1
时项目放大后宽 = 项目原始宽 + 剩余空间 * (flex-grow 值) / 所有项目的 flex-grow 值总和
案例 1
flex 容器存在剩余空间,且所有
flex-grow
值总和< 1
时
<style>
.flex-container {
width: 400px;
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
flex-wrap: wrap;
align-items: center;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
}
.flex-item:nth-child(1) {
flex-grow: 0.1;
background-color: tomato;
}
.flex-item:nth-child(2) {
flex-grow: 0.2;
background-color: khaki;
}
.flex-item:nth-child(3) {
flex-grow: 0.3;
background-color: pink;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
案例 2
flex 容器存在剩余空间,且所有
flex-grow
值总和>= 1
时
<style>
.flex-container {
width: 400px;
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
flex-wrap: wrap;
align-items: center;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
}
.flex-item:nth-child(1) {
flex-grow: 1;
background-color: tomato;
}
.flex-item:nth-child(2) {
flex-grow: 2;
background-color: khaki;
}
.flex-item:nth-child(3) {
flex-grow: 3;
background-color: pink;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
温馨提示:
flex 容器的剩余空间为 0 时,不管 flex 项目的flex-grow
的值是多少,flex 项都不会放大
# 4、flex-shrink 项目主轴上缩放系数
TIP
flex-shrink
属性指定了 flex 元素的收缩规则。- 当所有
flex
项目宽度之和大于容器的时候才会发生收缩(默认主轴为水平方向) - flex 项目收缩的大小是依据所有 flex 项的
flex-shrink
的值决定的。 flex-shrink
的默认值为1
,表示容器空间不足时,所有项目等比缩小- 只有当 flex 容器设置了
flex-wrap: nowrap;
时,才能看到效果
# (1)flex 项目收缩后尺寸大小计算
当 flex-shrink 所有值总和 < 1 时
- 第一步:计算溢出宽 = 所有项目宽 - 容器宽
- 第二步:所有子项的总缩放宽 = 溢出宽
*
所有项目flex-shrink
值之和 - 第三步:当前项目缩放比例 =(项目原始宽
*
flex-shrink 值)/ 每个项目宽*
flex-shrink 值 之和) - 第四步:项目收缩宽 = 所有子项的总缩放宽
*
当前缩放项的比例 - 第五步:项目收缩后宽 = 项目原始宽 - 项目收缩宽
<style>
.flex-container {
width: 400px;
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
align-items: center;
float: left;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
}
.flex-item:nth-child(1) {
background-color: tomato;
width: 300px;
flex-shrink: 0.1;
}
.flex-item:nth-child(2) {
background-color: khaki;
width: 200px;
flex-shrink: 0.2;
}
.flex-item:nth-child(3) {
background-color: pink;
width: 100px;
flex-shrink: 0.2;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
当 flex-shrink 所有值总和 >= 1 时
- 第一步:计算溢出宽 = 所有项目宽 - 容器宽
- 第二步:所有子项的总缩放宽 = 溢出宽
- 第三步:当前项目缩放比例 =(项目原始宽
*
flex-shrink 值)/ 每个项目宽*
flex-shrink 值 之和) - 第四步:项目收缩宽 = 所有子项的总缩放宽
*
当前缩放项的比例注:当项目的收缩宽 >项目原始宽时,此计算方式无效
- 第五步:项目收缩后宽 = 项目原始宽 - 项目收缩宽
<style>
.flex-container {
width: 400px;
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
align-items: center;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
}
.flex-item:nth-child(1) {
background-color: tomato;
width: 300px;
flex-shrink: 1;
}
.flex-item:nth-child(2) {
background-color: khaki;
width: 200px;
flex-shrink: 2;
}
.flex-item:nth-child(3) {
background-color: pink;
width: 100px;
flex-shrink: 3;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
- 多个 flex 项目,只有其中一个设置了 flex-shrink,且小于 1 时
主要是要考虑 flex-shrink 的默认值为 1
<style>
.flex-container {
width: 400px;
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
align-items: center;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
}
.flex-item:nth-child(1) {
background-color: tomato;
width: 300px;
flex-shrink: 0.5;
}
.flex-item:nth-child(2) {
background-color: khaki;
width: 200px;
}
.flex-item:nth-child(3) {
background-color: pink;
width: 100px;
}
/*
溢出宽=所有子项总宽(300+200+100) - 容器宽(400)=200
所有项目缩放总宽=溢出宽=200
项目1缩小后宽=300 - 300*0.5/(300*0.5+200*1+100*1)*200=300-150/450*200=233.3
项目2缩小后宽=200 - 200*1/(300*0.5+200*1+100*1)*200=200-200/450*200=111.1
项目1缩小后宽=100 - 100*1/(300*0.5+200*1+100*1)*200=100-100/450*200=55.5
*/
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
- 当
flex-shrink: 0;
时,无论如何不缩放,这种情况在实际开发中的用较多
<style>
.flex-container {
width: 400px;
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
align-items: center;
float: left;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
}
.flex-item:nth-child(1) {
background-color: tomato;
width: 300px;
flex-shrink: 0;
}
.flex-item:nth-child(2) {
background-color: khaki;
width: 200px;
flex-shrink: 1;
}
.flex-item:nth-child(3) {
background-color: pink;
width: 100px;
flex-shrink: 1;
}
/*
溢出宽=所有子项总宽(300+200+100) - 容器宽(400)=200
所有项目缩放总宽=溢出宽=200
项目1缩小后宽=300-0=300
项目2缩小后宽=200 - 200*2/(300*0+200*1+100*1)*200=200-200/300*200=66.67
项目1缩小后宽=100 - 100*3/(300*0+200*1+100*1)*200=100-100/300*200=33.3
*/
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
在实际开发中,用的最多的是以下两种情况
flex-shrink:0;
元素无任何如何不缩放- 所有元素的 flex-shrink 值,默认都为 1,等比缩小。
# 5、flex-basis 分配剩余空间前,项目占据主轴空间大小(main size)
TIP
flex-basis
属性定义了在分配多余空间之前,项目占据的主轴空间(main size)- 浏览器根据这个属性,计算主轴是否有多余空间。
- 它的默认值为
auto
,即项目的本来大小(如果width:200px
,则缩放以200px
为参考) flex-basis
的优先级要高于width
<style>
.flex-container {
width: 600px;
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
align-items: center;
}
.flex-item {
width: 50px;
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
}
.flex-item:nth-child(1) {
background-color: tomato;
width: 100px;
/* 剩余空间前,元素的大小 */
flex-basis: 200px;
flex-grow: 1;
}
.flex-item:nth-child(2) {
background-color: khaki;
width: 200px;
flex-grow: 2;
}
.flex-item:nth-child(3) {
background-color: pink;
width: 100px;
flex-grow: 3;
}
/*
剩余宽=600-(200+200+100)=100
项目1放大后宽=200+ 1/6*100=216.7
项目2放大后宽=200+ 2/6*100=233.3
项目3放大后宽=100+ 3/6*100=150
*/
</style>
<body>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
</div>
</body>
注意区分下面两种情况
/* 在计算剩余空间之前,元素宽为200px */
.flex-auto {
width: 200px;
/* 这里auto相当于200px */
flex-basis: auto;
}
/* 在计算剩余空间之前,元素的宽为0 */
.flex-auto {
width: 200px;
/* 这里相当于元素宽为 0 */
flex-basis: 0%;
}
# 6、flex 项目放大、缩小、空间占据
TIP
flex
属性是flex-grow
,flex-shrink
和flex-basis
的简写,默认值为0 1 auto
。- 2 个快捷值:
flex:auto;
表示:flex:1 1 auto;
flex:none;
表示:flex: 0 0 auto
建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。
flex:1
表示:flex:1 1 0%;
<style>
.flex-container {
height: 100px;
background-color: skyblue;
/* 弹性布局 */
display: flex;
/* 两端对齐 */
justify-content: space-between;
/* 垂直居中对齐 */
align-items: center;
}
.flex-item {
line-height: 50px;
font-size: 30px;
color: #fff;
text-align: center;
}
.flex-item:nth-child(1) {
background-color: tomato;
width: 200px;
}
.flex-item:nth-child(2) {
background-color: khaki;
overflow: hidden;
/* 文字不换行 */
white-space: nowrap;
/* flex:1相当于 flex:1 1 0%; */
flex: 1;
}
.flex-item:nth-child(3) {
width: 300px;
background-color: pink;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item">logo</div>
<div class="flex-item">搜索</div>
<div class="flex-item">登录</div>
</div>
</body>
# 四、Flex 实战
# 1、元素水平垂直居
<style>
.flex-container {
width: 200px;
height: 200px;
background-color: skyblue;
display: flex;
/* 水平居中 */
justify-content: center;
/* 垂直居中 */
align-items: center;
}
.flex-item {
width: 100px;
height: 100px;
background-color: khaki;
}
</style>
<body>
<div class="flex-container">
<div class="flex-item"></div>
</div>
</body>
# 2、画 3 色子
<style>
.dice {
width: 95px;
height: 95px;
border: 1px solid #666;
border-radius: 5px;
display: flex;
justify-content: space-between; /*两端对齐*/
padding: 5px;
}
.dice span {
width: 20px;
height: 20px;
background-color: #000;
border-radius: 50%;
}
/*色子2*/
.dice span:nth-child(2) {
align-self: center;
}
/*色子3*/
.dice span:last-child {
align-self: flex-end;
}
</style>
<body>
<div class="dice">
<span></span>
<span></span>
<span></span>
</div>
</body>
# 3、双飞翼布局
TIP
左右固定,中间自适应,最中间的内容放在第一位,有利用 SEO 搜索引擎优化。
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0;
}
.container {
display: flex;
height: 100%;
}
.middle {
flex-grow: 1;
background-color: khaki;
order: 1;
}
.left {
width: 200px;
background-color: skyblue;
order: 0;
}
.right {
width: 200px;
background-color: tomato;
order: 2;
}
</style>
<body>
<div class="container">
<div class="middle">中间</div>
<div class="left">左边</div>
<div class="right">右边</div>
</div>
</body>
# 4、flex 怎么实现盒子 1 在最左边,2 、3 在最右边
<style>
html,
body {
margin: 0;
padding: 0;
}
.container {
height: 200px;
border: 2px solid #000;
display: flex; /*弹性布局*/
justify-content: space-between; /*两端对齐*/
}
.container .left {
width: 300px;
background-color: tomato;
}
.container .right {
display: flex; /*弹性布局,这样子元素没有添加高度时,会和父元素一样高*/
}
.container .right .item1 {
width: 200px;
background-color: pink;
}
.container .right .item2 {
width: 100px;
background-color: skyblue;
}
</style>
<body>
<div class="container">
<div class="left"></div>
<div class="right">
<div class="item1"></div>
<div class="item2"></div>
</div>
</div>
</body>
# 5、星级评估
<style>
.rating {
display: flex;
align-items: center;
justify-content: center;
/*从右往左排列,关键性代码*/
flex-direction: row-reverse;
}
.rating-star {
position: relative;
margin: 0 2px;
font-size: 42px;
color: #ddd;
}
.rating-star::before {
/*实心星*/
content: "\2605";
left: 0px;
position: absolute;
}
/*鼠标滑动到星上时,星后面对应的星都变红*/
.rating-star:hover:before,
.rating-star:hover ~ .rating-star:before {
color: red;
}
</style>
<body>
<div class="rating">
<span class="rating-star">☆</span>
<span class="rating-star">☆</span>
<span class="rating-star">☆</span>
<span class="rating-star">☆</span>
<span class="rating-star">☆</span>
</div>
</body>
# 6、如何解决 flex 布局 7 个元素使用 space-between 最后一行两边分布的问题?
TIP
如果我们每一行显示的个数为 n,那我们可以最后一行子项的后面加上 n-2 个 span 元素,span 元素的宽度和其它子项元素宽度一样,但不用设置高度。
为什么是添加 n-2 个 span 元素呢 ?
- 当最后一行只有 1 个子元素时,他会默认靠左,不用处理
- 当最后一行子元素正好时,我们就不用关心这个问题。
所以要去掉这两种情况,只需要加 n-2 个 span 元素就好
案例演示:在没有加 n-2 个 span 元素前的效果
<style>
.container {
width: 500px;
display: flex; /*弹性布局*/
justify-content: space-between; /*两端对齐*/
flex-wrap: wrap; /*超出部分换行*/
}
.item {
width: 120px;
height: 100px;
background-color: pink;
margin-top: 10px;
}
</style>
<body>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
</div>
</body>
添加了 n-2
个 span 元素后效果(这里每行 4 个,4-2=2,所以只需要加 2 个 span 就可以了)如下所示:
<style>
.container span {
width: 120px;
} /*span宽和子项宽一样*/
</style>
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<span></span>
<span></span>
</div>
注:
如果想非常熟练的掌握 Flex 弹性布局,可以去博客看 102 个常见的布局案例,这 102 个常见的布局案例部都是采用最新 Flex 布局技术来实现的。
点击查看,102 个常见的 Flex 布局最佳实践 (opens new window) 👆
接下来的移动端的项目开发,我们就会采用最新的 Flex 布局来实现整站的页面开发。
# 五、专项案例训练(作业)
根据课程进度完成以下针对性案例开发,开发过程要求:
- 利用 PS(Photoshop)与 PxCook 结合,在 PS 中的找到 PxCook-切图面板,选中想要切图的图层 或者 图层组 ,然后点击切图面板上的 标记为切图 按钮 -> 再导出到 PxCook
- 在 PxCook 中下载对应的切图素材即可获取当前案例中的开发素材
- 开发过程中所需的尺寸在 PxCook 中量取
以上开发开发流程是用于个人训练从切图、量取尺寸,到具体的开发过程,包括平时自学中如果没有 PSD 源文件时,PxCook 是最佳的个人开发工具。因此现在阶段推荐使用这种方式来练习
在实际企业网页开发中(更多是团队协作开发,流程如下)
- 设计师设计好 UI 设计稿后 -> 会在 PS 中标记切图 -> 导出至蓝湖(国内企业用的多)中
- 前端开发人员下载网页开发所需的素材 -> 在蓝湖中量取尺寸 -> 即可开发静态页面
我们把 CSS/CSS3 基础知识全部学习完之后,会有 3 大项目开发(PC 端,响应式,移动端)会按照企业真实团队协作的方式,用 3 个项目来完整的实践。
PSD 的源文件设计稿(联系助理老师获取即可)
- 具体操作步骤讲解,在钉钉群直播回放视频(第十二课:CSS 盒子模型)中可查阅
切记
学习阶段一定要按照以上的流程学习,提前熟悉工具和整个开发步骤,企业真实项目开发就是这样的流程
# 1、Flex 开发酷狗音乐播放列表
点击查看完整版视频讲解
# 2、Flex 弹性布局(开发今日头条热门视频布局效果)
点击查看完整版视频讲解
# 3、Flex 弹性布局(开发微博热搜榜效果)
点击查看完整版视频讲解
大厂最新技术学习分享群
微信扫一扫进群,获取资料
X