flex布局的基本概念可以看一下阮一峰的文章www.ruanyifeng.com/blog/2015/0… 相信写过flex布局的同学基本都看过。这篇文章着重探究在实际开发中遇到的flex-grow,flex-shrink,flex-basic
一. 示例代码
- 实现1:1:1:1 布局
<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>flex布局</title>
</head>
<style>
.parent {
display: flex;
width: 800px;
height: 200px;
background-color: bisque;
}
.child1 {
flex: 1 1 0%;
background-color: cadetblue;
height: 100px;
}
.child2 {
flex: 1 1 0%;
background-color: coral;
height: 100px;
}
.child3 {
flex: 1 1 0%;
background-color: darkgreen;
height: 100px;
}
.child4 {
flex: 1 1 0%;
background-color: darkred;
height: 100px;
}
</style>
<body>
<div class="parent">
<div class="child1">child1</div>
<div class="child2">child2</div>
<div class="child3">child3</div>
<div class="child4">child4</div>
</div>
</body>
</html>
- 实现一个1:2:3:4等比布局?
.child1 {
flex: 1 1 0%;
background-color: cadetblue;
height: 100px;
}
.child2 {
flex: 2 1 0%;
background-color: coral;
height: 100px;
}
.child3 {
flex: 3 1 0%;
background-color: darkgreen;
height: 100px;
}
.child4 {
flex: 4 1 0%;
background-color: darkred;
height: 100px;
}
- 实现 20px : 1 : 3 : 100px 布局
.child1 {
flex: 0 0 20px;
background-color: cadetblue;
height: 100px;
word-break: break-all; // 不然子元素会超出去
}
.child2 {
flex: 1 1 0%;
background-color: coral;
height: 100px;
}
.child3 {
flex: 3 1 0%;
background-color: darkgreen;
height: 100px;
}
.child4 {
flex: 0 0 100px;
background-color: darkred;
height: 100px;
}
🌟踩坑 子元素中的内容溢出,会导致宽度不符合预期,所以需要注意一下。
.child1 {
flex: 0 0 20px;
background-color: cadetblue;
height: 100px;
/* word-break: break-all; */ 注释掉
}
二. 原理
如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。
所以,设置flex-basic: 0%,这个属性值会让父级主轴在计算剩余空间时忽略子元素的本身宽度,从而实现等比分配。
三. 宽度验证练习 公式:
剩余宽度: 父元素宽度 - 父元素两边的padding - flex-basis之和(有时候padding也算,具体情况具体分析)
平均一份剩余宽度: 剩余宽度 / (flexgrow之和)
子元素宽度:flex-basis + 按比例均摊到的剩余宽度 + (就不加上padding,具体情况具体分析)
- 如果parent是border-box,给父元素设置padding,会影响剩余长度。
<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>flex布局</title>
</head>
<style>
.parent {
display: flex;
padding: 0px 100px;
box-sizing: border-box;
width: 800px;
height: 200px;
background-color: bisque;
}
.child1 {
flex: 0 0 50px;
background-color: cadetblue;
height: 100px;
}
.child2 {
flex: 1 1 0%;
background-color: coral;
height: 100px;
}
.child3 {
flex: 3 1 0%;
background-color: darkgreen;
height: 100px;
}
.child4 {
flex: 0 0 100px;
background-color: darkred;
height: 100px;
}
</style>
<body>
<div class="parent">
<div class="child1">child1 50px</div>
<div class="child2">child2 112.5px</div>
<div class="child3">child3 337.5px</div>
<div class="child4">child4 100px</div>
</div>
</body>
</html>
计算步骤:
800px - (100px + 100px) - (50px + 100px) = 450px
450px / (1 + 3) = 112.5px
child2:0% * 800px + 112.5px * 1 = 112.5px
child: 0% * 800px + 112.5px * 3 = 337.5px
- 给子模块设置padding/margin,会在最终生成子元素宽度之后,加上padding。举例:
<!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>flex布局</title>
</head>
<style>
.parent {
display: flex;
padding: 0px 100px;
box-sizing: border-box;
width: 800px;
height: 200px;
background-color: bisque;
}
.child1 {
flex: 0 0 50px;
background-color: cadetblue;
height: 100px;
}
.child2 {
flex: 1 1 0%;
background-color: coral;
height: 100px;
padding-right: 20px;
}
.child3 {
flex: 3 1 0%;
background-color: darkgreen;
height: 100px;
padding-right: 30px;
}
.child4 {
flex: 0 0 100px;
background-color: darkred;
height: 100px;
}
</style>
<body>
<div class="parent">
<div class="child1">child1 50px</div>
<div class="child2">child2 100px + 20px</div>
<div class="child3">child3 300px + 30px</div>
<div class="child4">child4 100px</div>
</div>
</body>
</html>
计算步骤:
800px - (100px + 100px) - (50px + 100px + 20px + 30px) = 400px
400px / (1 + 3) = 100px
child2:0% * 800px + 100px * 1 + 20px = 120px
child: 0% * 800px + 1oopx * 3 + 30px = 330px
结论:
-
想要严格实现等比布局,flex-basic: 0%;
-
如果parent是border-box,给父元素设置padding,会影响剩余长度。
-
给子模块设置padding/margin, ①子模块box-sizing:boredr-box, 这个时候padding是作为宽度的一部分存在的,所以取max(padding, basic)作为主轴上的基础宽度。计算剩余宽度的时候要减掉这个basic。最终这个子元素的宽度就是
flex-basis + 按比例均摊到的剩余宽度②子模块box-sizing:content-box,这个时候padding是作为flex-basic之后,额外占位的一个宽度,所以计算剩余宽度的时候,要减去padding与flex-basic之和。最终这个子元素的宽度就是flex-basis + 按比例均摊到的剩余宽度 + padding
四. 补充:涉及到padding的例子
- child2 设置padding: 20px box-sizing: content-box;
<!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>flex布局</title>
</head>
<style>
.parent {
display: flex;
width: 800px;
height: 200px;
background-color: bisque;
}
.child1 {
flex: 0 0 50px;
background-color: cadetblue;
height: 100px;
}
.child2 {
flex: 1 1 10%;
background-color: coral;
/* box-sizing: border-box; */
height: 100px;
padding-right: 20px;
}
.child3 {
box-sizing: border-box;
flex: 3 1 20%;
background-color: darkgreen;
height: 100px;
}
.child4 {
flex: 0 0 100px;
background-color: darkred;
height: 100px;
}
</style>
<body>
<div class="parent">
<div class="child1">child1 50px</div>
<div class="child2">child2 177.5px + 20px</div>
<div class="child3">child3 452.5px</div>
<div class="child4">child4 100px</div>
</div>
</body>
</html>
计算步骤:
800px - (50px + 100px + 800px * 10% + 20px + 800px * 20%) = 390px
390px / (1 + 3) = 97.5px
child2:800px * 10% + 97.5px * 1 + 20px = 177.5px + 20px
child: 800px * 20% + 97.5 * 3 = 452.5px
- child2 设置padding: 20px box-sizing: border-box;
<!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>flex布局</title>
</head>
<style>
.parent {
display: flex;
width: 800px;
height: 200px;
background-color: bisque;
}
.child1 {
flex: 0 0 50px;
background-color: cadetblue;
height: 100px;
}
.child2 {
flex: 1 1 10%;
background-color: coral;
box-sizing: border-box; // !!!!
height: 100px;
padding-right: 20px;
}
.child3 {
box-sizing: border-box;
flex: 3 1 20%;
background-color: darkgreen;
height: 100px;
}
.child4 {
flex: 0 0 100px;
background-color: darkred;
height: 100px;
}
</style>
<body>
<div class="parent">
<div class="child1">child1 50px</div>
<div class="child2">child2 177.5px + 20px</div>
<div class="child3">child3 452.5px</div>
<div class="child4">child4 100px</div>
</div>
</body>
</html>
计算步骤:
realbasic = max(800px * 10%, 20) = 80px
800px - (50px + 100px + realbasic + 800px * 20%) = 410px
410px / (1 + 3) = 102.5px
child2:realbasic + 102.5px * 1 = 182.5px
child: 800px * 20% + 102.5 * 3 = 467.5px