BFC布局规则:css
简单示例:
1.自适应两栏布局
代码以下:html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>BFC</title> <style> body{ width:350px; position:relative; } div.sidebar{ float:left; width:100px; height:200px; background-color:#9deaf1; } div.main{ height:300px; background-color:#5dc2f6; } </style> </head> <body> <div class="sidebar"></div> <div class="main"></div> </body> </html>
页面效果图:css3
上述示例,正好反映了BFC布局规则:每一个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,不然相反)。即便存在浮动也是如此。
因此,sidebar虽然存在浮动,但main的左边依然与包含块的左边相接触。浏览器
2.BFC的区域不会与float box重叠。示例以下:app
代码:ide
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>BFC</title> <style> body{ width:350px; position:relative; } div.sidebar{ float:left; width:100px; height:200px; background-color:#9deaf1; } div.main{ height:300px; background-color:#5dc2f6; overflow:hidden; } </style> </head> <body> <div class="sidebar"></div> <div class="main"></div> </body> </html>
页面效果图:
经过overflow:hidden;触发main的BFC,main区域没有与float的sidebar重叠。说明了BFC的区域不会与float box重叠。布局
3.计算BFC的高度时,浮动元素也参与计算。url
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>BFC</title> <style> div.wrapper{ width:300px; border:2px solid #5dc2f6; } div.box{ width:100px; height:200px; background-color:#9deaf1; border:2px solid #5dc2f6; float:left; } </style> </head> <body> <div class="wrapper"> <div class="box"></div> <div class="box"></div> </div> </body> </html>
页面效果图:spa
咱们经过设计
div.wrapper{ width:300px; border:2px solid #5dc2f6; overflow:hidden; }
overflow:hidden; 触发wrapper的BFC,
清除box的浮动带来的影响,获得的页面效果图以下:
所以说明:计算BFC的高度时,浮动元素也参与计算。
4.清除垂直边距重叠
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>BFC</title> <style> div.box{ width:100px; height:100px; background-color:#9deaf1; border:2px solid #5dc2f6; } div.m50{ margin-bottom:50px; } div.m100{ margin-top:100px; } </style> </head> <body> <div class="box m50"></div> <div class="box m100"></div> </body> </html>
页面效果图以下:
如图所示,Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠。因此,两个div的垂直距离变成了100px,而不是150px了。
若是咱们给第二个div套上一层wrapper,而且触发外层的BFC,那么两个div就不是同一个BFC的两个相邻的Box了,而是变成两个独立的BFC。
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>BFC</title> <style> div.box{ width:100px; height:100px; background-color:#9deaf1; border:2px solid #5dc2f6; } div.wrapper{ overflow:hidden; } div.m50{ margin-bottom:50px; } div.m100{ margin-top:100px; } </style> </head> <body> <div class="box m50"></div> <div class="wrapper"> <div class="box m100"></div> </div> </body> </html>
页面效果图以下:
垂直边距再也不重叠,不是100px,而是150px了。
总结
以上事例都证实了:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。 由于BFC内部的元素和外部的元素绝对不会互相影响,所以, 当BFC外部存在浮动时,它不该该影响BFC内部Box的布局,因此BFC经过改变本身的宽度,实现不与浮动box有重叠。一样的,当BFC内部有浮动时,为了避免影响外部元素的布局,BFC计算高度时会包括浮动的高度。避免margin重叠也是这样的一个道理。
一. 在触发 hasLayout 的元素和建立了 Block Formatting Contexts 的元素中,浮动元素参与高度的计算
状况1:没有建立 Block formatting contexts 的块级非替换元素,触发了 IE 的 hasLayout。
分析如下代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>hasLayout 和 BFC</title> <style> div.wrapper{ width:300px; } div#container{ background-color:#9deaf1; zoom:1; } span#span1{ background-color:#5dc2f6; } div#div1{ width:150px; height:50px; background-color:#0576b0; } div#div2{ float:left; background-color:#4dd5b3; } </style> </head> <body> <div class="wrapper"> <div id="container"> <span id="span1">simple text</span> <div id="div1">in flow</div> <div id="div2">float:left</div> </div> </div> </body> </html>
根据 CSS2.1 规范第 10.6.3部分的高度计算规则,在进行普通流中的块级非替换元素的高度计算时,浮动子元素不参与计算。
因此,在进行 container 高度计算时,只受 span1 和 div1的影响,应该是它们两个的高度之和,因此最终container 的高度不包括div2的高度。
页面效果图在各浏览器的效果以下:
IE6 IE7:
IE8 Firefox Chrome Safari Opera:
当去掉container的zoom:1;各浏览器表现一致:
状况2:建立了 BFC的块级非替换元素,未触发 IE 的 hasLayout。
代码以下:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>hasLayout 和 BFC</title> <style> div.wrapper{ width:300px; } div#container{ background-color:#9deaf1; overflow:hidden; } span#span1{ background-color:#5dc2f6; } div#div1{ width:150px; height:50px; background-color:#0576b0; } div#div2{ float:left; background-color:#4dd5b3; } </style> </head> <body> <div class="wrapper"> <div id="container"> <span id="span1">simple text</span> <div id="div1">in flow</div> <div id="div2">float:left</div> </div> </div> </body> </html>
页面效果图以下:
IE6:
IE7/IE8/Firefox/Chrome/Safari/Opera
可见,只要 container 建立了 BFC,其浮动子元素就会参与其高度计算(IE7是因为触发了hasLayout 致使与其它浏览器的效果相同)。
二.与浮动元素相邻的、触发了 hasLayout 的元素或建立了 BFC 的元素,都不能与浮动元素相互覆盖。
与浮动元素相邻的、触发了 hasLayout 的元素或建立了 Block formatting contexts的元素,都不能与浮动元素相互覆盖。若是浮动元素的两侧有足够的空间放置该元素,则元素会紧邻浮动元素放置,必要时,该元素的宽度将会被压缩。不然它们可能会定位到浮动元素的下方。
状况1:没有建立BFC的块级非替换元素,触发了 IE 的 hasLayout。
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>hasLayout 和 BFC</title> <style> div#container{ border:2px solid #ddd; width:300px; height:150px; background:url("http://images0.cnblogs.com/ blog2015/790006/201508/041827351894332.png") repeat; } div#div1{ width:100px; height:100px; background-color:#9deaf1; float:left; filter:alpha("opacity=50"); opacity: 0.5; } div#div2{ background-color:green; zoom:1; } </style> </head> <body> <div id="container"> <div id="div1"> Float Block </div> <div id="div2"> 怀才就象怀孕,时间久了会让人看出来。 </div> </div> </body> </html>
IE6:
IE7/IE8
Firefox/Chrome/Safari/Opera
根据 CSS 2.1 9.5 Floats 中的描述,浮动元素会覆盖普通流中的块容器。因此,div2 应该有一部分被 div1 覆盖。
状况2:建立了 BFC的块级非替换元素,未触发 IE 的 hasLayout。
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>hasLayout 和 BFC</title> <style> div#container{ border:2px solid #ddd; width:300px; height:150px; background:url("http://images0.cnblogs.com/ blog2015/790006/201508/041827351894332.png") repeat; } div#div1{ width:100px; height:100px; background-color:#9deaf1; float:left; filter:alpha("opacity=50"); opacity: 0.5; } div#div2{ background-color:green; overflow:hidden; } </style> </head> <body> <div id="container"> <div id="div1"> Float Block </div> <div id="div2"> 怀才就象怀孕,时间久了会让人看出来。 </div> </div> </body> </html>
Firefox/Chrome/Safari/Opera:
IE6:
IE7/IE8
三. 触发 hasLayout 的元素和建立了 BFC的元素不会与它们的子元素发生外边距折叠
状况1:没有生成BFC的块级非替换元素,触发了 IE 的 hasLayout。
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>hasLayout和BFC</title> <style> div.box{ width:100px; height:100px; background-color:#9deaf1; border:2px solid #5dc2f6; } div.wrapper{ zoom:1; } div.m50{ margin-bottom:50px; } div.m100{ margin-top:100px; } </style> </head> <body> <div class="box m50"></div> <div class="wrapper"> <div class="box m100"></div> </div> </body> </html>
根据 CSS 2.1 8.3.1 Collapsing margins 第一条,两个相邻的普通流中的块框在垂直位置的空白边会发生折叠现象。
经过zoom:1;在IE中触发了hasLayout,因此,垂直边距不重叠,为150px。
而BFC未触发,因此垂直边距重叠,为100px;
IE6/IE7:
IE8/Firefox/Chrome/Safari/Opera:
状况2:生成 BFC的块级非替换元素,未触发 IE 的 hasLayout。
代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>BFC</title> <style> div.box{ width:100px; height:100px; background-color:#9deaf1; border:2px solid #5dc2f6; } div.wrapper{ overflow:hidden; } div.m50{ margin-bottom:50px; } div.m100{ margin-top:100px; } </style> </head> <body> <div class="box m50"></div> <div class="wrapper"> <div class="box m100"></div> </div> </body> </html>
IE6:
IE7/IE8/Firefox/Chrome/Safari/Opera:
IE7此时触发了hasLayout,但IE6没有触发hasLayout。
区别
共同点
可能产生的兼容性问题:
因为 hasLayout 和 BFC是对一类事物的不一样理解,而且他们的启用条件不尽相同,所以若是一个元素设计时,在 IE 早期版本中触发了 hasLayout ,但在其余浏览器中又没有建立BFC,或者相反,一个元素在 IE 早期版本中没有触发 hasLayout ,在其余浏览器中却建立了 BFC(如设置了 ‘overflow:hidden’ ),将致使页面布局的重大差别。
解决方案
仅当一个元素即在 IE 早期版本中触发了 hasLayout,又在其余浏览器中建立了BFC时,才能避免上述问题的发生。即同时启用上述二者以保证各浏览器的兼容,或者相反,二者皆不启用。 使元素即生成了BFC,又触发了 hasLayout 对于触发 hasLayout 的元素,经过 CSS 设置,使它产生BFC; 生成 BFC可是没有触发 hasLayout 的元素,经过设置 ‘zoom:1’,使其触发 hasLayout。 使元素即没有触发 hasLayout,又没有建立 BFC。
若有错误或者不足的地方,还望指正!----妙瞳
文章参考资料:
http://www.cnblogs.com/lhb25/p/inside-block-formatting-ontext.html
http://w3help.org/zh-cn/causes/RM8002