【主要内容】
用法规则,如何触发 BFC 以及 BFC 的一些用处(如清浮动,防止 margin 重叠等)
【简介】
BFC(Block Formatting Context块级格式化上下文),它规定了内部的块级元素的布局方式,默认情况下只有根元素(即body)一个块级上下文。通俗理解为页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素;外面的元素也不会影响到容器里面的子元素
1、BFC布局规则
①内部的块级元素会在垂直方向,一个接一个地放置;
②块级元素垂直方向的距离由margin决定。属于同一个BFC的两个相邻的块级元素会发生margin合并,不属于同一个BFC的两个相邻的块级元素不会发生margin合并;
③每个元素的margin box的左边,与包含border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此;
④BFC的区域不会与float box重叠(所以可以解决浮动造成的重叠覆盖问题);
⑤BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素;外面的元素也不会影响到容器里面的子元素;
⑥计算BFC的高度时,浮动元素也参与计算(所以可以消除浮动)
2、创建一个BFC
首先我们要知道怎样创建BFC。一个BFC可以被显式触发,只需满足以下条件之一:
float的值不为none;
overflow的值不为visible;
position的值为fixed / absolute;
display的值为table-cell / table-caption / inline-block / flex / inline-flex
3、BFC的应用
(1)消除margin合并
在之前文章里我写过相邻兄弟元素、父元素与第一个和最后一个子元素、空块元素的margin合并情况。那么对于发生margin合并的元素,我们怎样消除margin合并?
对于父子元素,我们可以通过设置padding、border、inline content、height、min-height、max-height等属性来消除;但是相邻的兄弟元素之间必出现margin合并,这时如果想要消除margin合并,又该怎么办?
我们首先要搞清楚为什么会发生margin合并
这些元素(包括兄弟、父子元素等)之间之所以会发生margin合并,是因为它们属于同一个BFC。所以,我们就知道怎么办了,只要让它们不属于同一个BFC不就可以了?
我们来举个例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>css1</title> <style type="text/css"> body { margin: 0; padding: 0; } .bro1 { width: 300px; height: 200px; background: #ddd; margin-bottom: 30px; } .bro2 { width: 200px; height: 100px; background: pink; margin-top: 20px; } </style> </head> <body> <div class='bro1'></div> <div class='bro2'></div> </body> </html>
结果显示为:30px;即合并后取了较大值----bor1的下外边距
【方案】
现在我们给.bro1新建一个BFC,并添加 overflow:hidden;
<div style="overflow:hidden"> <div class='bro1'></div> </div>
至此,margin合并消除了!
(2)包含浮动子元素
这也是我们的主要议题——为什么"overflow:hidden"能清除浮动的影响?
我们经常会在父元素里设置某个子元素浮动。浮动后,子元素脱离了文档流,使得父元素无法包住这个浮动的子元素。
通常在父元素上设置一个clearfix的伪元素来清除浮动;同样,我们可以利用BFC可以包含浮动这一特性来清除浮动,例子已经在之前讲过
我们对之前的例子作一个分析:当给父级设置"overflow:hidden"时,实际上创建了一个超级属性BFC,此超级属性反过来决定了"height:auto"是如何计算的
因为在“BFC布局规则”中提到:计算BFC的高度时,浮动元素也参与计算。因此,父元素在计算其高度时,加入了浮动元素的高度,“顺便”达成了清除浮动的目标,所以父元素就包裹住了子元素
(3)解决由于浮动造成的重叠覆盖问题
一般情况下,浮动元素会脱离文档流,即不占位置。它的兄弟元素会与它在左上角重叠。但是如果两个相邻元素都设置了浮动,那么意味着它们都是以BFC的规则渲染,根据上述第四条规则,BFC区域不会相互重叠,所以便能理解为什么设置浮动后元素能独占空间了
这里举个例子:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>css1</title> <style type="text/css"> body { margin: 0; padding: 0; } .bro1 { width: 200px; height: 200px; background: #ddd; float: left; } .bro2 { width: 200px; height: 200px; background: pink; /*display: inline-block, table-cell, table-caption, flex, inline-flex;*/ /*overflow: hidden;*/ } </style> </head> <body> <div class='bro1'></div> <div class='bro2'></div> </body> </html>给元素添加以下属性,即可激活BFC(块级格式化上下文)
float属性不为none;position为absolute或fixed;display为inline-block, table-cell, table-caption, flex, inline-flex;overflow不为visible
【注意】
①除了设置"overflow:hidden",我们还可以设置"display:inline-block"、"position:absolute"、"float:left"等方式来创建一个BFC,从而达到包裹浮动子元素的效果(具体使用哪种方法要看项目需求)
②IE6、7不支持伪元素,在IE6、7内有个hasLayout的概念,当元素的hasLayout属性值为true的时候会达到和BFC类似的效果。zoom:1 在IE6、7可以使hasLayout为true,所以如果清除浮动要兼容IE6、7,需要加上 zoom:1
③IE7及以下版本不支持BFC的,但有私有属性haslayout,于是我们可以通过触发元素的haslayout来达成bfc的相似效果
【拓展】
针对上面BFC布局规则第四条
④BFC的区域不会与float box重叠(所以可以解决浮动造成的重叠覆盖问题);
这里详细介绍下:
<div>元素A</div> <div>元素B</div>
代码效果如图:
当你元素A添加float属性后,元素A脱离文档流
正常情况下,后面元素B会与前面的元素A重叠(因为float导致A元素脱离文档流不再占据原来的位置,后面元素会占据前面的位置,如图)
元素产生BFC的原因{
根元素
float属性不为none
position为absolute或fixed
display为inline-block, table-cell, table-caption, flex, inline-flex
overflow不为visible
}
这个时候,我们任意选取上面一种原因加给元素B,比如加上overflow:hidden;
于是元素B 产生了BFC效果导致元素B收缩,不在占据元素A位置,如图
.