先说说FC,FC的含义就是Fomatting Context。它是CSS2.1规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
BFC和IFC都是常见的FC。分别叫做Block Fomatting Context 和Inline Formatting Context。
BFC(Block Formatting Context)叫做“块级格式化上下文”。
BFC的布局规则
1.内部的盒子会在垂直方向,一个个地放置;
2.盒子垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的上下margin会发生重叠。垂直方向上的距离会叠加,值由最大margin值决定(如果不要叠加,就需要将该盒子变成一个独立的盒子)
3.每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此;
4.BFC的区域不会与float重叠;
5.BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此;
6.计算BFC的高度时,浮动元素也参与计算。
形成BFC的条件
-
根元素(即body);
-
浮动元素,float的属性不为none;
-
定位元素,position为absolute或fixed;
-
display为inline-block,table-cell,table-caption,flex;
-
overflow不为visible。(值为hidden/auto/scroll时)
BFC的作用
-
解决margin重叠的问题(添加独立BFC)
-
解决浮动高度塌陷的问题(在父级添加overflow:hidden)
-
解决侵占浮动元素的问题(添加overflow:hidden清除浮动)
BFC特性详解
接下来我将用例子一一对其特性进行说明。
特性一
内部的盒子会在垂直方向,一个个地放置。
这个很好理解,body本身就是一个BFC,根据块级元素的定义,块级元素是会占满一整行的。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BFC</title>
<style>
.container {
width: 300px;
border: 1px solid #000;
/*触发BFC*/
overflow: hidden;
height: 400px;
}
.box1 {
height: 20px;
width: 50%;
background-color: blue;
}
.box2 {
height: 20px;
width: 50%;
background-color: yellow;
}
</style>
</head>
<body>
<div class="container">
<div class="box1"></div>
<div class="box2"></div>
</div>
</body>
</html>

特性二
盒子垂直方向的距离由margin决定,属于同一个BFC的两个相邻Box的上下margin会发生重叠。垂直方向上的距离会叠加,值由最大margin值决定(如果不要叠加,就需要将该盒子变成一个独立的盒子)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BFC</title>
<style>
.container {
width: 300px;
border: 1px solid #000;
/*触发BFC*/
overflow: hidden;
height: 400px;
}
.box1{
height: 20px;
margin: 50px 0;
background-color: blue;
}
.box2{
height: 20px;
margin: 60px 0;
background-color: yellow;
}
</style>
</head>
<body>
<div class="container">
<div class="box1"></div>
<div class="box2"></div>
</div>
</body>
</html>

如果希望这两个盒子之间的margin不要重叠,则需要使其中一个盒子形成一个独立容器,即触发BFC。
这也是利用了BFC的第五个特性。
-
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BFC</title>
<style>
.container {
width: 300px;
border: 1px solid #000;
/*触发BFC*/
overflow: hidden;
height: 400px;
}
.wrapper {
width: 100%;
overflow: hidden;
border: 2px solid purple;
}
.box1 {
height: 20px;
margin: 50px 0;
background-color: blue;
}
.box2 {
height: 20px;
margin: 60px 0;
background-color: yellow;
}
</style>
</head>
<body>
<div class="container">
<div class="box1"></div>
<div class="wrapper">
<div class="box2"></div>
</div>
</div>
</body>
</html>

特性三
3、每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此;
第三点也很好理解,就拿body来说,文档流都是从左往右排版的。即使存在浮动元素,BFC中其他元素的margin box的左边也会与包含块border box的左边相接触 。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box {
background: gray;
}
.left {
/* 即使存在浮动元素,BFC中其他元素的margin box的左边也会与包含块border box的左边相接触 */
/* 在这个例子中,黄框向左浮动,脱离了普通流,此时绿框被定位到包含块的左上角 */
float: left;
width: 100px;
height: 80px;
background: yellow;
opacity: .5;
}
.right {
width: 200px;
height: 50px;
background: green;
opacity: .5;
}
</style>
</head>
<body>
<div class='box'>
<div class="left"></div>
<div class="right"></div>
</div>
</body>
</html>

特性四
BFC的区域不会与float重叠;
现有如下代码,左盒子设置成浮动,右边是普通的块级div。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BFC</title>
<style>
.box1 {
/*浮动触发bfc*/
float: left;
width: 200px;
height: 200px;
background-color: blue;
text-align: right;
}
.box2 {
width: 500px;
height: 300px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="box1">右侧文字</div>
<div class="box2">左侧文字</div>
</body>
</html>
效果如图,左盒子由于被设置成向左浮动,触发了BFC,而右盒子未触发BFC,有部分区域被覆盖了。

现在将右盒子也触发BFC。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BFC</title>
<style>
.box1 {
/*浮动触发bfc*/
float: left;
width: 200px;
height: 200px;
background-color: blue;
text-align: right;
}
.box2 {
/*overflow触发bfc, 这里用float:left也行*/
overflow: hidden;
width: 500px;
height: 300px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="box1">右侧文字</div>
<div class="box2">左侧文字</div>
</body>
</html>
效果如下。

特性五
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之也如此;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BFC</title>
<style>
.container01 {
/*触发父盒子bfc*/
float: left;
width: 600px;
border: 2px solid black;
/* 高度靠内容撑开*/
}
.container02{
/*触发父盒子bfc*/
float: left;
width: 600px;
border: 2px solid black;
}
.box1 {
/*浮动触发bfc*/
float: left;
width: 1000px;
height: 200px;
background-color: blue;
}
.box2 {
/*浮动触发bfc*/
float: left;
width: 1000px;
height: 200px;
background-color: yellow;
}
</style>
</head>
<body>
<div class="container01">
<div class="box1">内容</div>
</div>
<div class="container02">
<div class="box2">内容</div>
</div>
</body>
</html>
效果如图,左右盒子互不干涉。

特性六
计算BFC的高度时,浮动元素也参与计算。
这个就是常见的去浮动的原理,触发BFC,面试中经常会问到的。
现有如下代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BFC</title>
<style>
.container {
width: 600px;
border: 2px solid black;
/* 高度靠内容撑开*/
}
.box1 {
/*浮动触发bfc*/
float: left;
width: 200px;
height: 200px;
background-color: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="box1">内容</div>
</div>
</body>
</html>
效果如下图,可以看到,由于子盒子的浮动,父盒子的高度未被子盒子撑开,因而塌陷了。

这时触发父元素形成BFC,就会将浮动元素的高度也计算入内了。
.container {
/*触发父盒子bfc*/
overflow: hidden;
width: 600px;
border: 2px solid black;
/* 高度靠内容撑开*/
}

BFC应用场景
自适应两栏布局
现有如下代码,想要实现一个自适应的两栏布局。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
div {
width: 300px;
}
.aside {
width: 100px;
height: 150px;
float: left;
background: black;
}
.main {
height:200px;
background-color:red;
}
</style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>
效果如图。

现在想要将黑色区域和红色区域分开来,不允许有重叠。
因为body本身就是一个BFC,这满足了规范的第三条:
-
每个元素的左边,与包含的盒子的左边相接触,即使存在浮动也是如此。
所以如果我们需要将黑色区域撑到红色的左边,就需要利用规范的第四条:
-
BFC的区域不会与float重叠。
也就是说我们需要创造BFC区域。可以通过将红色区域的overflow设为hidden来触发BFC:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
div {
width: 300px;
}
.aside {
width: 100px;
height: 150px;
float: left;
background: black;
}
.main {
/*形成BFC*/
overflow:hidden;
height:200px;
background-color:red;
}
</style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>

清除浮动
现有如下代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>BFC</title>
<style>
.container {
width: 600px;
border: 2px solid black;
/* 高度靠内容撑开*/
}
.box1 {
/*浮动触发bfc*/
float: left;
width: 200px;
height: 200px;
background-color: blue;
}
</style>
</head>
<body>
<div class="container">
<div class="box1">内容</div>
</div>
</body>
</html>
效果如下图,可以看到,由于子盒子的浮动,父盒子的高度未被子盒子撑开,因而塌陷了。

这时触发父元素形成BFC,就会将浮动元素的高度也计算入内了。
.container {
/*触发父盒子bfc*/
overflow: hidden;
width: 600px;
border: 2px solid black;
/* 高度靠内容撑开*/
}

margin重叠
先定义两个垂直的div:
<div class="p"></div>
<div class="p"></div>
然后定义margin:
.p {
width:200px;
height:50px;
margin:50px 0;
background-color:red;
}
可以看到margin重叠后的效果:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.p {
width: 200px;
height: 50px;
margin: 50px 0;
background-color: red;
}
</style>
</head>
<body>
<div class="p"></div>
<div class="p"></div>
</body>
</html>

再看看BFC规范的第二条:
-
盒子垂直方向的距离由margin决定,属于用一个BFC的两个相邻Box的上下margin会发生重叠。
说明两者属于同一个BFC,所以我们需要两个div不属于同一个BFC。
为第二个div套一个父亲div,然后将其overflow设为hidden来激活一个BFC就可以使margin不再重叠。
<div class="p"></div>
<div class="wrap">
<div class="p"></div>
</div>
.wrap {
overflow:hidden;
}
最终效果如下。

原文始发于微信公众号(豆子前端):一文带你彻底弄懂BFC
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/56930.html