一、BFC概念
BFC 即 Block Formatting Contexts (块级格式化上下文),是W3C CSS2.1规范中的一个概念,决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。具有BFC特性的元素可以看做是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且BFC具有普通容器所没有的的一些特性。
二、BFC生成条件
只要元素满足下面任一条件即可触发BFC特性:
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex
- overflow 除了 visible 以外的值(hidden、auto、scroll)
三、BFC的约束规则
BFC的约束规则
浏览器对于BFC这块区域的约束规则如下:
- 生成BFC元素的子元素会一个接一个的放置。垂直方向上他们的起点是一个包含块的顶部,俩个相邻子元素之间垂直距离取决于元素margin特性。在BFC中相邻的块级元素外边距会折叠。
- 生成BFC元素的子元素中,每一个子元素的外边距和包含块的左边界相接触,(对于从右到左的格式化,右外边距和右边界相接触),除非这个子元素也创建了一个新的BFC(如它自身也是一个浮动元素)。
有朋友对它做了分解,我们直接拿来:
- 内部的BOX会在垂直方向上一个接一个的放置;
- 垂直方向上的距离有margin决定。(完整的说法是:属于同一个BFC的俩个相邻的BOX的margin会发生重叠,与方向无关。)
- 每个元素的左外边距与包含块的左边界相接触(从左到右),即使浮动元素也是如此。(这说明BFC中的子元素不会超出它的包含块,而position为absolute的元素可以超出它的包含块边界);
- BFC的区域不会与float的元素区域重叠;
- 计算BFC的高度时,浮动子元素也参与计算;
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
CSS的几条规则:
- Block元素会扩展到与父元素同宽,所以block元素会垂直排列;
- 垂直方向上的俩个相邻DIV的margin会重叠,而水平方向不会(此规则并不完全正确);
- 浮动元素会尽量往左上方(或右下方);
- 为父元素设置overflow:hidden或浮动父元素,则会包含浮动元素;
BFC应用场景
1.防止margin重叠
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style type="text/css">
.box{
overflow: hidden;//触发BFC
}
.box p{
width: 100px;
height: 100px;
background-color: antiquewhite;
margin: 20px;
}
</style>
</head>
<body>
<div class="box">
<p></p>
</div>
<div class="box">
<p></p>
</div>
</body>
</html>
如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。
如下图,margin不重叠
2.浮动相关问题
高度塌陷问题,在通常情况下父元素的高度会被子元素撑开,而在这里因为其子元素为浮动元素所以父元素发生了高度坍塌,上下边界重合,这时就可以用BFC来清除浮动了。
<div style="border: 1px solid #000;">
<div style="width: 100px;height: 100px;background: grey;float: left;"></div>
</div>
由于容器内元素浮动,脱离了文档流,所以容器只剩下2px的边距高度。如果触发容器的BFC,那么容器将会包裹浮动元素。
<div style="border: 1px solid #000;overflow: hidden">
<div style="width: 100px;height: 100px;background: grey;float: left;"></div>
</div>
3.阻止元素被浮动元素覆盖
div浮动兄弟这该问题:由于左侧块级元素发生了浮动,所以和右侧未发生浮动的块级元素不在同一层内,所以会发生div遮挡问题。可以给右侧元素添加 overflow: hidden,触发BFC来解决遮挡问题。
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一个左浮动的元素</div>
<div style="width: 200px; height: 200px;background: grey">我是一个没有设置浮动,
也没有触发 BFC 元素, width: 200px; height:200px; background: grey;</div>
这时候其实第二个元素有部分被浮动元素所覆盖,但是文本信息不会被浮动元素所覆盖,如果想避免元素被覆盖,可触发第二个元素的BFC特性,在第二个元素中加入overflow:hidden,就会变成:
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一个左浮动的元素</div>
<div style="width: 200px; height: 200px;background: grey;overflow:hidden">我是一个没有设置浮动,
也没有触发 BFC 元素, width: 200px; height:200px; background: grey;</div>
这个方法可以用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度。
清除浮动
1、尾部添加div
<div>
<p style="float:left">
</p>
<div style="clear:both"></div>
</div>
这个方法通俗点将就是,父元素下面的子元素都浮动了,如果有一个不浮动岂不是就能包住了?没错这个方法就是尾部添加div的方式思想。
2、伪类清除
<style>
.clearfix{
*zoom:1;
}
.clearfix:after{
content:"";
display:block;
clear:both;
}
</style>
<div class="clearfix">
<ul style="float:left">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
3、BFC处理
也就是触发BFC的生成条件
3.1、设置父元素float的值不为none
<div style="float:left">
<ul style="float:left">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
3.2、设置父元素overflow的值不为visible
<div style="overflow:hidden">
<ul style="float:left">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
3.3、display的值为inline-block、table-cell、table-caption
<div style="display:inline-block">
<ul style="float:left">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>
用这个方法时注意ie8不支持inline-block
3.4、position的值为absolute或fixed
<div style="position:fixed">
<ul style="float:left">
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
</div>