超详细弹性布局解析!一篇文章让你彻底掌握Flexbox
目录
弹性布局是CSS引进的一种布局模型,可以控制子元素的排列方向,对齐方式,空间分配和换行,
全称为Flexible Box,其核心概念有四个,分别为设置弹性容器(flex contaniner),弹性项目(flex item),主轴(main axis)和交叉轴(cross axis)接下来将详细讲解弹性容器和弹性项目的属性
弹性容器
首先,什么是弹性容器呢,简单来说,任何一个元素,只要设置了display:flex或display:inline-flex,那么这个元素就变成了弹性容器,弹性容器的直接子元素会变成弹性项目,那display:flex和display:inline-flex又是什么呢
display:flex:块级元素,独占一行
display:inline-flex:内联元素,会于其他内容同行,且宽度由内容撑开
主轴属性
弹性容器内部有两根看不见的轴,这两根轴是掌握所有容器属性的关键,主轴(main axis)是弹性项目主要排列的方向,水平方向,默认为从左到右,有起点(main start)和终点(main end),还有一根是交叉轴(cross axis),是垂直方向,默认为从上到下,同样的,交叉轴也有起点(cross start)和终点(cross end),接下来我们要学习的是主轴的相关属性
| 属性 | 可选值 | 默认值 | 作用 |
| display |
flex(块级弹性容器) inline-flex(内联弹性容器) |
---- | 开启弹性布局 |
| flex-direcion |
row(从左到右) row-reverse(从右到左) coulm(从上到下) coulm-revers(从下到上) |
row | 设置主轴反向 |
| flex-wrap |
nowrap(不换行) wrap(换行) wrap-revers(反向换行) |
nowrap | 控制是否换行 |
| flex-flow |
方向+换行 例如 row wrap |
row nowrap | 同时设置方向和换行 |
| justify-content |
flex-start(起始对齐) flex-end(末尾对齐) center(居中对齐) space-evenly(均匀对齐) space-around(环绕对齐) space-between(两端对齐) |
flex-start | 设置项目的对齐方式 |
| column-gap | 长度值 | 0 | 设置主轴方向上的间距 |
看完了属性,那么就要用代码来实验一下了
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>弹性容器主轴</title>
<style>
/* 主轴属性演示 */
.a {
display: flex; /* 开启块级弹性容器 */
flex-direction: row; /* 主轴方向:水平从左到右 */
flex-wrap: wrap; /* 允许换行(宽度不足时换行) */
justify-content: space-evenly; /* 主轴对齐:均匀间距 */
gap: 20px 15px; /* 行间距20px(交叉轴),列间距15px(主轴) */
background: #e0f7fa; /* 设置背景颜色 */
border: 2px solid #00796b; /* 设置边框 */
padding: 10px; /* 内边距 */
width: 350px; /* 限制宽度,使换行效果可见 */
}
.b {
background: #ffb74d;
padding: 10px 20px;
width: 80px; /* 固定宽度,一行最多放3个 */
text-align: center;
}
</style>
</head>
<body>
<div class="a">
<div class="b">1</div>
<div class="b">2</div>
<div class="b">3</div>
<div class="b">4</div>
</div>
</body>
</html>

交叉轴属性
交叉轴的属性和主轴的其实大差不差,其中有一个值是可以同时设置主轴和交叉轴的间距,那就是<gap>,可以在后面设置两个值,同时设置交叉轴方向的行间距和主轴方向的列间距,格式为
gap:行间距 列间距,接下来看看交叉轴的属性设置吧
| 属性 | 可选值 | 默认值 | 作用 |
| align-items |
stretch(拉伸) flex-start(起始对齐) flex-end(末尾对齐) centrer(居中对齐) baseline(基线对齐) |
stretdh | 单行项目在交叉轴上的对齐方式 |
| align-content |
stretch(拉伸) flex-start(起始对齐) flex-end(末尾对齐) centrer(居中对齐) space-between(两端对齐) space-around(环绕对齐) |
stretch | 多行项目在交叉轴上的对齐方式(主轴上需要有flex-wrap:wrap并产生多行) |
| row-gap | 长度值 | 设置交叉轴方向上的项目间距 |
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>弹性容器交叉轴</title>
<style>
.a {
display: flex;
flex-direction: row; /* 主轴水平,交叉轴垂直 */
align-items: center; /* 交叉轴对齐:居中对齐(垂直居中) */
width: 300px; /*宽度*/
height: 150px; /* 高度*/
background: #ced2e9;
border: 2px solid #1229ac;
gap: 10px;
padding: 10px;
margin-bottom:20px ;
}
.a .e{
background: #afbaf0;
padding: 10px;
color: white;
}
/* 不同高度项目突出交叉轴效果 */
.a .b:first-child { height: 40px; }
.a .b:nth-child(2) { height: 60px; }
.a .b:last-child { height: 80px; }
.b {
display: flex;
flex-direction: row;
flex-wrap: wrap; /* 必须换行才能产生多行 */
align-content: center; /* 多行整体在交叉轴居中 */
height: 250px; /* 固定高度,让多行居中效果明显 */
background: #fff3e0;
border: 2px solid #ff9800;
row-gap: 20px; /* 单独设置交叉轴方向的行间距 */
column-gap: 10px; /* 主轴列间距 */
padding: 10px;
width: 300px;
}
.b .e {
background: #81c784;
width: 80px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
}
</style>
</head>
<body>
<div class="a">
<div class="e">999</div>
<div class="e">888</div>
<div class="e">666</div>
</div>
<div class="b">
<div class="e">1</div>
<div class="e">2</div>
<div class="e">3</div>
<div class="e">4</div>
<div class="e">5</div>
<div class="e">6</div>
</div>
</body>
</html>
弹性项目
弹性项目的属性是写在弹性容器里面的子元素上的,可以用来单独控制每个项目,来看看弹性项目的属性吧
属性
| 属性 | 可选值 | 默认值 | 作用 |
| order | 整数(可以是负数) | 0 | 设置数字来决定排列顺序,数字越大越靠后 |
| flex-grow | 非负数 | 0 | 剩余空间的放大比例(0代表不放大,1代表所有元素一起平分剩余空间) |
| flex-shrink | 非负数 | 1 | 空间不足时的缩小比例(0代表不缩小,1代表所有元素一起按比例缩小) |
| flex-basis | 长度/auto/content | auto | 分配剩余空间前的初始空间 |
| flex |
复合属性 flex-grow flex-basis |
0 1 auto | 简写,同时设置上面三个属性,常用的flex:1表示 1 1 0% |
| align-self |
auto(继承父级) stretch(拉伸) flex-start(起始对齐) flex-end(末尾对齐) center(居中对齐) baseline(基线对齐) |
auto | 覆盖容器的属性设置,可以单独对元素进行设置 |
属性详解
其实弹性容器的属性还比较通俗易懂,但是这个弹性项目的却叫人眼花缭乱,感觉作用晦涩难懂,其实我也有这种困扰,所以我单独对弹性项目的属性去查阅了资料,整理了一下,把各种专业名词拆成容易理解的大白话,下面来看看我的详细讲解吧
order
这个属性简单来说就是让已经拍好的队形进行重排,我们都知道,在默认情况下,元素的顺序是按照写代码的顺序,从上到下来排列的,但是order可以改变这个顺序,元素在设置了这个属性后,会按照设置的数字来排列,数字越小,排的越靠前,而且是可以设置负数的,而元素的默认值是0,顺序按上下来排,如果在几个元素中单独给一个元素设置order的值为负数,那么这个元素就会排到最前面,单独设置一个元素的值为大于0 的数,那么这个元素无论处于代码中的哪个地方,最终的排序他都会处于最后面
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>order</title>
<style>
.a{
display: flex;
gap: 10px;
background-color: aqua;
}
#c{order:1}
#d{order:-1}
</style>
</head>
<body>
<div class="a">
<div id="b">111</div>
<div id="c">222</div>
<div id="d">333</div>
</div>
</body>
</html>

flex-grow
这个属性俗称吃剩饭,当容器内还有多余的空间时,设置这个属性的值超过0,元素就会按比例瓜分剩下的多余空间,具体分的是宽度还是高度,那就要看主轴的方向了。那选中就有人要问了,这个按比例分配具体是怎么分呢,打个比方,主轴的方向是水平,那么分配的就是宽度,此时宽度为500px,前面不参与分配的元素已经占了200px,还剩300px,后面有两个元素要参与分配,A设置为flex-grow:1,B为flex-grow:2,那A的宽度为300/(1+2)*1=100px,B为300/(1+2)*2=200px,也就是说参与分配的元素分配后最终的宽度计算公式为{剩余空间/(所有参与分配的元素的flex-grow总和)*(自己的flex-grow值)}。如果主轴的方向是垂直方向,流程也不变,主轴朝哪边,他就分哪边。但是有一个点要注意,那就是元素的内边距、外边距、边框和gap属性都会间接影响到分配的空间,当设置了这些属性时,会先扣除这些属性所占用的空间,剩下的再进行分配
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flex-grow</title>
<style>
.a{
display: flex;
width: 500px;
height: 500px;
gap: 10px;
background-color: aqua;
}
#b{
width: 200px;
background-color: rgb(224, 213, 2)
}
#c{
flex-grow: 1;
background-color: rgb(138, 231, 7);
}
#d{
flex-grow: 2;
background-color: rgb(247, 36, 3);
}
</style>
</head>
<body>
<div class="a">
<div id="b">111</div>
<div id="c">222</div>
<div id="d">333</div>
</div>
</body>
</html>

flex-shrink
既然有吃剩饭,那相反的,也会有吃不饱,只能挨饿,缩小自己,容器有过大的时候,也会有偏小的时候,那容器都不够大了,里面装的满满的元素为了不被挤出去,也只能跟着缩小,和上面的flex-drow差不多,都是按比例来缩小,而为了防止元素挤出容器,这个属性默认值是1,也就是默认按比例缩小,当然,也可以设置为flex-shrink:0,这样的话被设置的元素就不会因为容器的空间不足而按比例缩小,虽然缩小也是按比例来的,但是和放大不一样,缩小按的是权重比例。所有元素都会按一个加权比例来分担不足空间,先用容器的宽度减去所有元素相加的总宽度得到不足的空间,然后每个元素要用自己的flex-shrink值乘以自身的宽度,再把所有元素的权重相加得到总权重,之后用每个元素的自身的宽度除以总权重来得到缩小的权重比例,最后用不足的空间乘以每个元素的缩小权重来得到需要缩小的宽度,拿元素本身的宽度减去需要缩小的宽度就能得到最终的宽度,看起来很复杂,其实也确实挺复杂。我们来举个栗子,一个容器是300px,A元素是200px,B元素是300px,不足的空间是500-300=200,A元素的flex-shrink值是1,B的值也是1,那么A的权重是1*200=200,B的权重为1*300=300,总权重=500,A的缩小比例就是200/500=0.4,B的比例为300/500=0.6,可以算出A的最终宽度为200-200*0.4=120px,B的宽度为200-300*0.6=180px,总结一下,缩小的计算公式为{元素自身宽度-不足空间*元素权重/总权重=元素最终宽度}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>flex-shrink</title>
<style>
.a{
display: flex;
width: 300px;
height: 300px;
gap: 10px;
background-color: aqua;
}
#c{
width: 200px;
flex-shrink: 1;
background-color: rgb(138, 231, 7);
}
#d{
width: 300px;
flex-shrink: 1;
background-color: rgb(247, 36, 3);
}
</style>
</head>
<body>
<div class="a">
<div id="c">222</div>
<div id="d">333</div>
</div>
</body>
</html>

flex-basis
相比于上面两个,这个属性属于特别简单的了,flex-basis属性就是弹性项目再分配剩余空间之前的初始尺寸,该属性可以定义的值有四个,分别是auto,意思是自动,设置了这个,元素会想查找自己的宽高设置,如果没有设置宽高的话,那么该元素的尺寸则由内容直接撑开;conter,为内容尺寸,会直接根据内容自动计算尺寸,如果设置了宽高,会被直接忽略掉,但是兼容性较晚,反倒不如auto常用;<长度>,直接输入长度,50px,20rem,50%等,输入的是百分比的话,则会相对于父容器尺寸;0,强制元素初始尺寸为0,完全依赖剩余空间分配(flex-grow);
flex
这是一个简写,相当于同时去定义flex-grow,flex-shrink,flex-basis这三个属性,最常用的是flex:1,这等同于flex-grow:1,flex-shrink:1,flex-basis:0%,也就是可大可小,初始尺寸为0,完全根据剩余的空间来进行分配;flex:auto,相当于1 1 auto,同样可大可小,初始尺寸由内容来决定;flex:none,相当于0 0 auto,这个既不长大,也不缩小,完全由内容决定尺寸;除了这几个,还有就是手动指定,根据flex-grow,flex-shrink,flex-basis的位置来输入值,用这个可以使代码看起来简洁很多,写起来也方便
align-self
这个属性比较横,通俗点就是我行我素,父容器用align-items来控制所以头项目再交叉轴上的对齐方式,用这个属性就可以脱离父容器的掌控,优先级凌驾于容器之上,用来单独控制元素的对齐
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)