先说说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;
}
最终效果如下。