说起页面的布局,不得不提一个容易忽略但是很重要的东西——BFC(block formatting context),翻译的直接点就是块级格式化上下文,翻译的有意境点就是开辟自己的地盘。以下是我对BFC的一些理解:
一、什么是BFC
BFC是一个独立的渲染区域,只有block-level box参与,它规定了内部的block-level box如何布局,并且与这个区域外部毫不相干。(也就是创建一个封闭空间,与世隔绝)。
block-level box:块级元素。display属性为block, list-item, table的元素,会生成block-level box;并且参与 block fomatting context。
inline-level box:行内元素。display 属性为 inline, inline-block, inline-table的元素,会生成inline-level box。并且参与 inline formatting context。
二、哪些元素有成为BFC的资质
display属性为block,list-item,table。这三个都是用来布局最为合理的元素,因为他们就是用来可视化布局。也就是说不是所有的元素都可以称为BFC的,你必须有万里挑一的天赋,经过修炼,关键时刻才能让你出来拯救世界。相当于《功夫》里的周星驰,拥有万中无一的天赋。
三、什么条件下可以让元素产生BFC
float属性不为none;
overflow不为visible;
position属性为absolute或者fixed;
display为inline-block,table-cell,table,caption,flex,inline-flex
四、BFC元素所具有的特性
(1)在BFC中,盒子从顶端开始垂直地一个接一个地排列。
(2)盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻盒子垂直方向的margin会发生重叠。
(3)在BFC中,每一个盒子的左外边距(margin-left)会触碰到容器的左外边缘(border-left),对于从右往左的格式来说,会触碰到右边缘。
(4)BFC不会与浮动盒子产生交集,而是紧贴浮动元素边缘。
(5)计算BFC高度BFC时,自然也会检测浮动的子盒子高度。
五、布局中BFC的应用
(1)清除盒子垂直方向上外边距合并——盒子垂直方向的距离由margin决定。属于同一个BFC的两个相邻盒子垂直方向的margin会发生重叠。
初始代码和效果图如下:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>垂直方向上外边距合并问题</title>
<style>
* {
margin: 0;
padding: 0;
}
.father {
background-color: #f0f;
width: 300px;
}
.father>div {
width: 200px;
height: 200px;
background-color: #ffc107;
}
.son1 {
margin-bottom: 100px;
}
.son2 {
margin-top: 50px;
}
</style>
</head>
<body>
<div class="father">
<div class="son1"></div>
<div class="son2"></div>
</div>
</body>
</html>
使用BFC解决外边距合并问题,代码和效果图如下:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>垂直方向上外边距合并问题</title>
<style>
* {
margin: 0;
padding: 0;
}
.father {
background-color: #f0f;
width: 300px;
}
.son1,.son2 {
width: 200px;
height: 200px;
background-color: #ffc107;
}
.son1 {
margin-bottom: 100px;
}
.son2 {
margin-top: 50px;
}
.fason {
overflow: hidden;
}
</style>
</head>
<body>
<div class="father">
<div class="son1"></div>
<div class="fason">
<div class="son2"></div>
</div>
</div>
</body>
</html>
根据属于同一个BFC的两个相邻盒子垂直方向的margin会发生重叠的性质,可以给son2盒子再包裹一个盒子fason,并触发其BFC功能这样son1和son2就不在同一个BFC中了,因此也不会发生垂直外边距合并的问题了。
(2)制作右侧自适应盒子——BFC不会与浮动盒子产生交集,而是紧贴浮动元素边缘。
代码和效果图如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>右侧自适应盒子</title>
margin: 0;
<style> * {
.fu {
padding: 0; }
height: 500px;
width: 400px;
margin: 0 auto;
background-color: #f0f; } .son1 {
background-color: #0ff;
width: 50px; height: 100px; float: left; }
}
.son2 { background-color: #ff0; overflow: hidden; </style></head>
我在右边,但是我可以自适应,你看,我不是在自适应吗?
<body><div class="fu"> <div class="son1"></div> <div class="son2">
我在右边,但是我可以自适应,你看,我不是在自适应吗?
我在右边,但是我可以自适应,你看,我不是在自适应吗? 我在右边,但是我可以自适应,你看,我不是在自适应吗? 我在右边,但是我可以自适应,你看,我不是在自适应吗?
我在右边,但是我可以自适应,你看,我不是在自适应吗?
我在右边,但是我可以自适应,你看,我不是在自适应吗? 我在右边,但是我可以自适应,你看,我不是在自适应吗? 我在右边,但是我可以自适应,你看,我不是在自适应吗? 我在右边,但是我可以自适应,你看,我不是在自适应吗?
</html>
我在右边,但是我可以自适应,你看,我不是在自适应吗? 我在右边,但是我可以自适应,你看,我不是在自适应吗? </div></div>
</body>
修改左侧蓝颜色盒子的宽度,右侧是盒子仍然可以自适应,代码和效果图如下:
.son1 {
width: 50px;
height: 100px;
background-color: #0ff;
float: left;
}
由于BFC的盒子是独立的,所以不会和浮动的盒子产生交集,而右侧的黄色盒子没有设置宽度,靠内容撑开,所以产生了自适应。
(3)清除浮动——计算BFC高度时,自然也会检测浮动的子盒子高度。
未加浮动代码和效果图如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>清除浮动</title>
<style>
* {
margin: 0;
padding: 0;
}
.father {
width: 500px;
background-color: #f00;
border: 5px solid #000;
margin: 0 auto;
}
.son1 {
width: 200px;
height: 200px;
background-color: #00f;
}
</style>
</head>
<body>
<div class="father">
<div class="son1"></div>
</div>
</body>
</html>
给son盒子加浮动的代码和效果图如下:
.son1 {
width: 200px;
height: 200px;
background-color: #00f;
float: left;
}
清除浮动代码和效果图如下:
.father {
width: 500px;
background-color: #f00;
margin: 0 auto;
overflow: hidden;
}
由于在计算BFC高度时,自然也会检测浮动的子盒子高度。所以当子盒子有高度但是浮动的时候,通过激发父盒子的BFC功能,会产生清除浮动的效果。
注:html默认有BFC
细心的童鞋肯定发现了在清除垂直外边距合并的案例中,父盒子中的子盒子的垂直方向上的外边距合并了,父盒子却并没有设置BFC功能。这是因为html默认创建BFC功能,而父盒子被html中的BFC渲染到,所以其子盒子垂直外边距才会产生合并。这一点很少被提及,也很容易被大多数人忽略。
文中我只使用了overflow:hidden;的方法激发盒子的BFC功能,大家在使用的时候,可以试一试其他的方式,多去尝试,多思考,会发现惊喜噢!!!