Flexbox 布局是一种用于按行或按列
布局元素的一维布局
方法,可以使元素自动调整大小
以适应可用空间
Flexbox布局允许元素膨胀以填充额外的空间,也可以收缩以适应更小的空间
基本构成
flex布局主要由以下两个部分组成
分类 | 说明 |
---|---|
flex container | 开启了 flex 布局的那个元素 --- 父容器 |
flex item | flex container 里面的直接子元素 --- 容器中的元素 |
Flex item 的特点:
- flex item的布局将根据
flex container属性值来进行布局
- flex item
不再严格区分块级元素和行内级元素
- flex item
默认情况下是包裹内容的
, 但是可以设置宽度和高度
开启flex布局
我们可以设置display属性的值为flex
或者inline-flex
来为当前元素开启弹性布局
flex类型 | 说明 |
---|---|
flex | flex container 以 block-level 形式存在 |
inline-flex | flex container 以inline-level 形式存在 |
盒子模型
flex item
会沿着主轴(从 main-start 到 main-end
)或横轴(从 cross-start 到 cross-end
)排列
container相关属性
flex-direction
flex items 默认都是沿着 main axis(主轴)从 main start 开始往 main end 方向排布
flex-direction 决定了 main axis 的方向
,因此我们可以使用flex-direction
来改变元素的排列方向
值 | 说明 |
---|---|
row | 元素从左往右排列,默认值 |
row-reverse | 元素从右往左排列 |
column | 元素从上往下排列 |
column-reverse | 元素从下往上排列 |
flex-wrap
flex-wrap 决定了 flex container 是单行还是多行
值 | 说明 |
---|---|
nowrap | 单行显示,不换行 --- 默认值 |
wrap | 多行显示 |
wrap-reverse | 多行 对比 wrap,cross start 与 cross end 相反 |
在默认情况下,Flexbox 布局的 flex-wrap
属性值为 nowrap
,这意味着它不会换行。当一行中的元素放不下时,Flexbox 布局会尽可能地压缩元素的宽度或高度来适应可用空间
因此,即使为 Flexbox 布局中的元素显示设置了对应的宽度和高度,元素最终展示出来的宽度或高度可能与所设置的宽度和高度不同。元素的显示设置的宽度和高度只能说存在关系,但不是必然的结果
flex-flow
flex-flow 属性是 flex-direction 和 flex-wrap 的简写,并且顺序任何, 并且都可以省略
<flex-direction> || <flex-wrap>
justify-content
justify-content 决定了flex items在 main axis上的对齐方式
值 | 说明 | 示意图 |
---|---|---|
flex-start | 与 main start 对齐 默认值 | |
flex-end | 与 main end 对齐 | |
center | 居中对齐 | |
space-between | 与 main start、main end两端对齐 flex items 之间的距离相等 | |
space-around | flex items 与 main start、main end 之间的距离是 flex items 之间距离的一半 flex items 之间的距离相等 | |
space-evenly | flex items 与 main start、main end 之间的距离 等于 flex items 之间的距离 flex items 之间的距离相等 |
align-items
align-items 决定了 flex items在cross axis上的对齐方式
值 | 说明 | 示意图 |
---|---|---|
normal | 在弹性布局中,效果和stretch一样 默认值 | |
strech | 当 flex items 在 cross axis 方向的 size 为 auto 时 会 自动拉伸至填充 flex container | |
flex-start | 与 cross start 对齐 | |
flex-end | 与 cross end 对齐 | |
center | 居中对齐 | |
baseline | 与基准线对齐 |
align-content
align-content 决定了多行flex items在cross axis上的对齐方式
,用法与 justify-content 类似
值 | 说明 | 示意图 |
---|---|---|
stretch | 与 align-items 的 stretch 类似 默认值 | |
flex-start | 与 cross start 对齐 | |
flex-end | 与 cross end 对齐 | |
center | 居中对齐 | |
space-between | 与justify-content的space-between效果一致 | |
space-around | 与justify-content的space-around效果一致 | |
space-evenly | 与justify-content的space-evenly效果一致 |
align-content
使用的先决条件
- 必须有多行
align-items
- 必须存在剩余空间,可以给
flex container
划分空间
所以align-content
在实际开发中很少使用,因为在实际开发中,在绝大多数情况下,
flex-container的高度是由flex-items中的内容撑开的
这也就意味着,没有剩余的空间给align-content
进行分配, 此时设置或者不设置align-content
属性,效果都是一致的
item相关属性
order
order 决定了 flex items 的排布顺序
- 可以设置任意整数
(正整数、负整数、0)
- 值越小就越排在前面,
- 如果值相同,则值相同的元素按照默认先后顺序排列
- 默认值是 0
align-self
flex items 可以通过 align-self 覆盖 flex container 设置的 align-items
- auto(默认值): 遵从 flex container 的 align-items 设置
- stretch、flex-start、flex-end、center、baseline,效果跟 align-items 一致
flex-grow
flex-grow 决定了 flex items 如何扩展 (拉伸/成长)
- 可以设置任意非负数字(
正小数、正整数、0
),默认值是 0
- 当 flex container 在 main axis 方向上
有剩余 size
时,flex-grow 属性才会有效
- flex items 扩展后的最终 size 不能超过
max-width/max-height
flex-grow拉伸的计算方式如下:
flex items 的 flex-grow 总和 sum | 每个 flex item 扩展后的 size |
---|---|
大于1 | flex container 的剩余size * flex-grow / sum |
小于1 | flex container 的剩余 size * flex-grow |
flex-shrink
flex-shrink 决定了 flex items 如何收缩(缩小)
-
可以设置任意非负数字(
正小数、正整数、0
),默认值是 1
-
当 flex items 在 main axis 方向上
超过了 flex container 的 size
,flex-shrink 属性才会有效, 也就是元素溢出了,flex-shrink
才会生效 -
flex items 收缩后的最终 size 不能小于
min-width/min-height
-
如果没有设置最小高度或最小高度,则不小于flex-item中
内容的宽度或高度
flex-shrink
的计算方式如下:
-
如果
flex-shrink
总和大于1,则:-
计算总的缩放宽度:
total shrink scaled width=∑(width×flex-shrink)
-
计算每个元素的缩放比例:
shrink ratio=width×flex-shrink / total shrink scaled width
-
计算新的宽度:
new width=width−(shrunk space×shrink ratio)
-
-
如果
flex-shrink
总和小于1,则原width - 原宽度 * flex-shrink
flex-basis
flex-basis
属性用于设置 Flexbox 布局中flex-item
在主轴上的初始大小, flex-basis
的优先级高于width/height
flex-basis
属性只会影响flex-item
在 Flexbox 布局的初始大小,flex-item
的后续大小取决于他们在flex-cotainer
中是如何布局的
换句话说width
和 height
属性在设置后值基本不会发生改变,但是flex-basis的值可能会根据flex布局而重新调整
需要注意的是,如果flex-basis
和width/height
同时存在,那么该flex-item
可以设置的最大宽度或高度为width/height
flex-basis
可以取的值:
auto (默认值)
- 如果没有设置width,那么默认值表现为内容的宽度
- 如果设置width,那么默认值表现为width
- 具体的宽度数值(100px)
- 可以是一个百分比
- 该百分比相对的是其父弹性盒容器主轴尺寸
决定 flex items 最终 base size 的因素,从优先级高到低:
- max-width / max-height / min-width / min-height
- flex-basis
- width / height
- 内容本身的 size
flex
flex 是 <flex-grow> <flex-shirink>? || <flex-basis>
的简写
flex 属性可以指定1个,2个或3个值
# flex: none --> flex: 0 0 auto;
# flex: auto --> flex: 1 1 auto;
# flex: initial --> flex: 0 1 auto; ---> 恢复为默认初始值
none | auto | initial | <flex-grow> <flex-shirink>? || <flex-basis>
单值语法: 值必须为以下其中之一:
- 一个无单位数(
<number>
): 它会被当作<flex-grow>
的值 - 一个有效的宽度(
width
)值: 它会被当作<flex-basis>
的值 - 关键字none,auto
**双值语法: **
第一个值必须为一个无单位数,并且它会被当作 <flex-grow>
的值
第二个值必须为以下之一:
- 一个无单位数:它会被当作
<flex-shrink>
的值 - 一个有效的宽度值: 它会被当作
<flex-basis>
的值
三值语法:
- 第一个值必须为一个无单位数,并且它会被当作
<flex-grow>
的值 - 第二个值必须为一个无单位数,并且它会被当作
<flex-shrink>
的值 - 第三个值必须为一个有效的宽度值, 并且它会被当作
<flex-basis>
的值
flex布局应用
flex最后一行对齐问题
在绝大多数情况下,我们希望前面几行是按照我们所需要的布局进行排列,而最后一行是从左往右依次排列
例如; 在上述图中,我们希望第一行和第二行实现space-between
, 而最后一行实现从左往右依次进行排列
也就是实现如下图效果
解决方法一
通过计算,手动去设置对应的margin来实现排列效果,而不是使用justify-content
属性
不推荐,因为如果元素个数 或 宽度值(flex-item的或flex-container的)发生改变后,需要重新计算,扩展性不强
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 600px;
background-color: gray;
display: flex;
flex-wrap: wrap;
/*
通过手动计算margin值来实现布局
所以在这样不需要再通过justify-content来进行布局
*/
/* justify-content: space-between; */
}
.item {
width: 160px;
height: 160px;
color: #fff;
font-size: 20px;
line-height: 160px;
text-align: center;
margin-bottom: 20px;
/*
margin-right = (600 - 160 * 3)/ 2
*/
margin-right: 60px;
}
/* 最右边那一列元素移除margin-right的值 */
.item:nth-child(3n) {
margin-right: 0;
}
/* 最后3个节点 移除下外边距 */
.item:nth-last-child(-n + 3) {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
<div class="item item4">item4</div>
<div class="item item5">item5</div>
<div class="item item6">item6</div>
<div class="item item7">item7</div>
<div class="item item8">item8</div>
</div>
<!-- 该脚本用于生成div.item的随机色 -->
<script src="./index.js" ></script>
</body>
</html>
解决方法二
为最后填充不可见的占位元素,确保元素的总数可以被列数所整除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 600px;
background-color: gray;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.item {
width: 160px;
height: 160px;
color: #fff;
font-size: 20px;
line-height: 160px;
text-align: center;
margin-bottom: 20px;
}
span {
/*
只要保证span元素的宽度 === div.item的宽度即可
因为span的高度默认的0
所以理论上设置任意个数的span都不会影响flex布局的最终显示效果
但是一般最少设置的个数为 列数 - 2
*/
width: 160px;
}
/*
本例中显示的是三例
所以需要至少添加一个占位元素
那么就意味着在本案例中需要为最后4个元素清除下外边距
*/
:nth-last-child(-n + 4) {
margin-bottom: 0;
}
</style>
</head>
<body>
<div class="container">
<div class="item item1">item1</div>
<div class="item item2">item2</div>
<div class="item item3">item3</div>
<div class="item item4">item4</div>
<div class="item item5">item5</div>
<div class="item item6">item6</div>
<div class="item item7">item7</div>
<div class="item item8">item8</div>
<!--
1. 需要填充的元素的个数是列数-2
2. span在这里的作用仅仅只是为了做布局的额外填充元素
所以在这里可以使用任何元素来作为填充元素,不一定是span元素
推荐使用i元素,因为i元素只有一个字符,所占字符最小
-->
<span></span>
</div>
<!-- 该脚本用于生成div.item的随机色 -->
<script src="./index.js" ></script>
</body>
</html>
flex属性结合溢出隐藏
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 300px;
background-color: gray;
display: flex;
margin: 100px auto;
}
.center {
/*
div.center的宽度自动占满剩余空间
相当于视情况 动态设置div.center的宽度
所以在这里也可以使用溢出省略号的效果
*/
flex: 1;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
background-color: skyblue;
}
</style>
</head>
<body>
<div class="container">
<div class="left">left part</div>
<div class="center">Lorem ipsum dolor sit amet consectetur adipisicing elit. Fugit, nisi.</div>
<div class="right">right part</div>
</div>
</body>
</html>
flex: 1 和 text-overflow: ellipsis冲突问题
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
width: 600px;
display: flex;
list-style: none;
}
.item {
height: 100px;
background-color: skyblue;
border: 1px solid gray;
}
.item1,
.item3 {
width: 100px;
}
.item2 {
flex: 1;
/* min-width: 0; */
overflow: hidden;
}
span {
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
display: block;
}
</style>
</head>
<body>
<ul class="container">
<li class="item item1">lorem</li>
<!--
如果一个元素的父元素设置了flex: 1;
而该元素上设置了text-overflow: ellipsis;
那么flex:1 就会和 text-overflow: ellipsis; 产生冲突
原因:
父元素flex:1; 子元素 text-overflow: ellipsis;的时候
浏览器会认为 当前元素的宽度值是auto; 是可以被撑开的
因此此时子元素就没有了width的限制,所以text-overflow: ellipsis;无效
解决方法:
1. 子元素必须是块级元素(如果子元素不是块级元素,需要先转换为块级元素)
2, 父元素设置`min-width: 0;`或`overflow`不为`visible`的值(一般设置为`none`或`auto`)
-->
<li class="item item2">
<span>Lorem ipsum, dolor sit amet consectetur adipisicing elit. Aut maxime facere voluptate fugiat adipisci sunt ipsam reprehenderit ullam ut et!</span>
</li>
<li class="item item3">lorem</li>
</ul>
</body>
</html>