其实答案很简单,那就是 Flex 布局好用。一个新事物的出现往往是因为旧事物不那么好用了,比如,如果想让你用传统的 css 布局来实现一个块元素垂直水平居中你会怎么做?实现水平居中很简单,margin: 0 auto
就行,而实现垂直水平居中则可以使用定位实现:
<div class="container">
<div class="item"></div>
</div>
.container {
position: relative;
width: 300px;
height: 300px;
background: red;
}
.item {
position: absolute;
background: black;
width: 50px;
height: 50px;
margin: auto;
left: 0;
top: 0;
bottom: 0;
right: 0;
}
或者
.item {
position: absolute;
background: black;
width: 50px;
height: 50px;
margin: auto;
left: calc(50% - 25px;
top: calc(50% - 25px;
}
.container {
width: 300px;
height: 300px;
background: red;
display: flex;
place-content: center;
}
.item {
background: black;
width: 50px;
height: 50px;
}
接下来的本篇文章将会带领大家一起来探讨Flex
布局
基本概念
html
<div class="container">
<div class="item">flex项目</div>
<div class="item">flex项目</div>
<div class="item">flex项目</div>
<div class="item">flex项目</div>
</div>
.container {
display: flex;
width: 800px;
gap: 10px;
}
.item {
color: #fff;
}
flex 容器
flex 容器比如container
元素
flex 项目
flex 项目,比如item
元素
轴
主轴和交叉轴,至于哪个是主轴哪个是交叉轴则有flex 容器的flex-direction
属性决定,默认为:flex-direction:row
,既横向为主轴,纵向为交叉轴,
flex-direction还可以设置其它三个属性,分别为row-reverse
,column
,column-reverse
。
-
row-reverse
-
column
-
column-reverse
flex-direction的影响
不足空间和剩余空间
Flex 项目之间的间距
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
</div>
.container {
display: flex;
width: 500px;
height: 400px;
gap: 10px;
}
.item {
width: 150px;
height: 40px;
}
Flex 属性
flex属性是flex-grow
,flex-shrink
,flex-basis
三个属性的简写。下面我们来看下它们分别是什么。
-
flex-grow为 Flex 项目的扩展系数,当 Flex 项目总和小于 Flex 容器时就会出现剩余空间,而
flex-grow
的值则可以决定这个 Flex 项目可以分到多少剩余空间 -
flex-shrink为 Flex 项目的收缩系数,同样的,当 Flex 项目总和大于 Flex 容器时就会出现不足空间,
flex-shrink
的值则可以决定这个 Flex 项目需要减去多少不足空间
flex-basis可以设定 Flex 项目的大小,一般主轴为水平方向的话和 width 解析方式相同,但是它不一定是 Flex 项目最终大小,Flex 项目最终大小受到flex-grow
,flex-shrink
以及剩余空间等影响,后面文章会告诉大家最终大小的计算方式
flex属性是这三个属性的简写,那么flex
属性简写方式分别代表什么呢?
flex属性可以为 1 个值,2 个值,3 个值,接下来我们就分别来看看它们代表什么意思
- 一个值
flex属性只有一个值的话,我们可以看这个值是否带单位,带单位那就是flex-basis
,不带就是flex-grow
.item {
flex: 1;
/* 相当于 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
.item {
flex: 30px;
/* 相当于 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 30px;
}
- 两个值
当flex
属性有两个值的话,第一个无单位的值就是flex-grow
,第一个无单位的值则是flex-shrink
,有单位的就是flex-basis
.item {
flex: 1 2;
/* 相当于 */
flex-grow: 1;
flex-shrink: 2;
flex-basis: 0;
}
.item {
flex: 30px 2;
/* 相当于 */
flex-grow: 2;
flex-shrink: 1;
flex-basis: 30px;
}
- 三个值
当flex
属性有三个值的话,第一个无单位的值就是flex-grow
,第一个无单位的值则是flex-shrink
,有单位的就是flex-basis
.item {
flex: 1 2 10px;
/* 相当于 */
flex-grow: 1;
flex-shrink: 2;
flex-basis: 10px;
}
.item {
flex: 30px 2 1;
/* 相当于 */
flex-grow: 2;
flex-shrink: 1;
flex-basis: 30px;
}
.item {
flex: 2 30px 1;
/* 相当于 */
flex-grow: 2;
flex-shrink: 1;
flex-basis: 30px;
}
另外,flex 的值还可以为initial
,auto
,none
。
- initial
.item {
flex: initial;
/* 相当于 */
flex-grow: 0;
flex-shrink: 1;
flex-basis: auto;
}
- auto
当 flex 设置为 auto 时,Flex 项目会根据自身内容确定flex-basis
,既会拓展也会收缩
.item {
flex: auto;
/* 相当于 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: auto;
}
- none
none 表示 Flex 项目既不收缩,也不会扩展
.item {
flex: none;
/* 相当于 */
flex-grow: 0;
flex-shrink: 0;
flex-basis: auto;
}
Flex 项目大小的计算
首先看一下 flex-grow 的计算方式
flex-grow
同样的我们先举个例子
<div class="container">
<div class="item">Xiaoyue</div>
<div class="item">June</div>
<div class="item">Alice</div>
<div class="item">Youhu</div>
<div class="item">Liehuhu</div>
</div>
.container {
display: flex;
width: 800px;
}
.item {
flex: 1;
font-size: 30px;
}
flex 容器总宽度为 800px,flex 项目设置为flex:1
,此时页面上显示
首先
.item {
flex: 1;
/* 相当于 */
flex-grow: 1;
flex-shrink: 1;
flex-basis: 0;
}
因为flex-basis
为 0,所有 Flex 项目扩展系数都是 1,所以它们分到的剩余空间都是一样的。下面看一下是如何计算出最终项目大小的
Flex项目弹性量 = (Flex容器剩余空间/所有flex-grow总和*当前Flex项目的flex-grow
Flex项目弹性量指的是分配给 Flex 项目多少的剩余空间,所以 Flex 项目的最终宽度为
flex-basis+Flex项目弹性量
。flex-basis为 0,所以剩余空间就是 800px,每个 Flex 项目的弹性量也就是
(800/1+1+1+1+1*1=160
,那么最终宽度也就是160+0=160
<div class="container"> <div class="item">Xiaoyueyueyue</div> <div class="item">June</div> <div class="item">Alice</div> <div class="item">Youhu</div> <div class="item">Liehu</div> </div>
此时会发现 Flex 容器并没有被均分
min-content(217.16px,此时浏览器会采用 Flex 项目的
min-content
作为最终宽度,而后面的 Flex 项目会在第一个 Flex 项目计算完毕后再进行同样的计算.item { text-align: center; flex: 1 100px; }
因为每个项目的
flex-basis
都是 100px,Flex 容器剩余空间为800-500=300px
,所以弹性量就是(300/5*1=60px
,最终宽度理论应该为100+60=160px
,同样的因为第一个 Flex 项目的min-content
为 217.16px,所以第一个 Flex 项目宽度被设置为 217.16px,最终表现和上面一样800-217.16-100*4=182.84,第 2 个 Flex 项目弹性量为
(182.84/1+1+1+1*1=45.71
,所以最终宽度为100+45.71=145.71px
,同样的后面的 Flex 项目计算方式是一样的,但是如果后面再遇到长单词,假如第五个是长单词,那么不足空间将会发生变化,浏览器会将第五个 Flex 项目宽度计算完毕后再回头进行一轮计算,具体情况这里不再展开min-width设置为 0 即可
.item { flex: 1 100px; min-width: 0; }
flex-grow 为小数
<div class="container"> <div class="item">Acc</div> <div class="item">Bc</div> <div class="item">C</div> <div class="item">DDD</div> <div class="item">E</div> </div>
.item:nth-of-type(1 { flex-grow: 0.1; } .item:nth-of-type(2 { flex-grow: 0.2; } .item:nth-of-type(3 { flex-grow: 0.2; } .item:nth-of-type(4 { flex-grow: 0.1; } .item:nth-of-type(5 { flex-grow: 0.1; }
效果如图
弹性量计算方式为
Flex项目弹性量=Flex容器剩余空间*当前Flex项目的flex-grow
flex-basis+弹性量,首先先不设置 flex-grow,我们可以看到每个项目的 flex-basis 分别为: 51.2 , 33.88 , 20.08 , 68.56 , 16.5
800-51.2 -33.88 - 20.08 - 68.56 - 16.5=609.78,这样我们就可以算出每个项目的实际尺寸为
实际宽度 = 51.2 + 609.78*0.1 = 112.178
实际宽度 = 33.88 + 609.78*0.2 = 155.836
下面看下 flex-grow 之和大于 1 的情况,将例子中的 css 改为
.item:nth-of-type(1 { flex-grow: 0.1; } .item:nth-of-type(2 { flex-grow: 0.2; } .item:nth-of-type(3 { flex-grow: 0.3; } .item:nth-of-type(4 { flex-grow: 0.4; } .item:nth-of-type(5 { flex-grow: 0.5; }
此时的效果为
Flex项目弹性量 = (Flex容器剩余空间/所有flex-grow总和*当前Flex项目的flex-grow
Flex 项目的 flex-grow 之和小于 1,Flex 项目不会占满 Flex 容器
flex-shrink
修改一下我们的例子:
.item { flex-basis: 200px; /* 相当于 */ flex-shrink: 1; flex-grow: 0; flex-basis: 200px; }
此时项目的总宽度
200*5=1000px
已经大于容器总宽度800px
,此时计算第一个项目的不足空间就是800-200*5=-200px
,第二个项目的不足空间则是800-第一个项目实际宽度-200*4
,依次类推Flex项目弹性量 = (Flex容器不足空间/所有flex-shrink总和*当前Flex项目的flex-shrink
第一个 Flex 项目:
200+((800-200x5/5*1 = 160px
200+((800-160-200x4/4*1 = 160px
200+((800-160-160-200x3/3*1 = 160px
200+((800-160-160-160-200x2/2*1 = 160px
200+((800-160-160-160-160-200x1/1*1 = 160px
min-content大于
flex-basis
,那么最终的实际宽度将会取该项目的min-content
,比如改一下例子,将第一个 Flex 项目改成长单词<div class="container"> <div class="item">XiaoyueXiaoyue</div> <div class="item">June</div> <div class="item">Alice</div> <div class="item">Youhu</div> <div class="item">Liehu</div> </div>
min-content作为实际宽度,相应的后面 Flex 项目的宽度会等前一个 Flex 项目计算完毕后在进行计算
200+((800-228.75-200x4/4*1 = 142.81px
flex-shrink 为小数
.item { flex-basis: 200px; flex-shrink: 0.1; }
效果为
Flex 项目的 flex-shrink 之和小于 1,Flex 项目会溢出 Flex 容器
Flex项目弹性量=Flex容器不足空间*当前Flex项目的flex-shrink
Flex项目实际宽度=flex-basis + Flex项目弹性量
第一个 Flex 项目宽度 =
200+(800-200x5x0.1=180px
,但是由于它本身的min-content
为 228.75,所以最终宽度为 228.75200-(800-228.75-200x4x0.1=117.125
Flex 的对齐方式
Flex 中关于对齐方式的属性有很多,其主要分为两种,一是主轴对齐方式:justify-*,二是交叉轴对齐方式:align-*
<div class="container"> <div class="item">A</div> <div class="item">B</div> <div class="item">C</div> </div>
.container { display: flex; width: 500px; height: 400px; } .item { width: 100px; height: 40px; }
主轴对齐属性
justify-content
justify-content的值可以为:
- flex-start 默认值,主轴起点对齐
- flex-end 主轴终点对齐
- left 默认情况下和 flex-start 一致
- right 默认情况下和 flex-end 一致
- center 主轴居中对齐
- space-between 主轴两端对齐,并且 Flex 项目间距相等
- space-around 项目左右周围空间相等
- space-evenly 任何两个项目之间的间距以及边缘的空间相等
交叉轴对齐方式
align-content
**注意设置 align-content 属性时候必须将 flex-wrap 设置成 wrap 或者 wrap-reverse。**它可以取得值为
- stretch 默认值,当我们 Flex 元素不设置高度的时候,默认是拉伸的
.item {
width: 100px;
}
- flex-start 位于容器开头,这个和 flex-direction:属性有关,默认在顶部
- flex-end 位于容器结尾
- center 元素居中对齐
- space-between 交叉轴上下对齐,并且 Flex 项目上下间距相等
.item {
width: 300px;
}
- space-around 项目上下周围空间相等
- space-evenly 任何两个项目之间的上下间距以及边缘的空间相等
align-items
stretch 默认值,当我们 Flex 元素不设置高度的时候,默认是拉伸的
-
flex-end 位于容器结尾
比如给 A 项目一个 padding-top
.item:nth-of-type(1 {
padding-top: 50px;
}
没设置 baseline 的表现
align-self
上面都是给 Flex 容器设置的属性,但是如果想要控制单个 Flex 项目的对齐方式该怎么办呢?
align-self 和 align-items 属性值几乎是一致的,比如我们将整个 Flex 项目设置为 center,第二个 Flex 项目设置为 flex-start
.container {
display: flex;
width: 500px;
height: 400px;
align-items: center;
}
.item {
width: 100px;
height: 40px;
}
.item:nth-of-type(2 {
align-self: flex-start;
}
交叉轴与主轴简写
place-content
place-content
为justify-content
和align-content
的简写形式,可以取一个值和两个值,如果设置一个值那么justify-content
和align-content
都为这个值,如果是两个值,第一个值为align-content
,第二个则是justify-content
点个赞吧~