BFC与hasLayout都是CSS布局上的概念。
几个月前在微博上才了解什么是BFC,算是对布局有点初步的了解。
hasLayout则是IE6、7产生许多bug的根源。
浮动、绝对定位元素,不是块框的块容器(inline-block, table-cell, and table-caption),以及设置了overflow属性(除了visible)的块框,它们会为它们的内容形成新的 block formatting contexts (BFC)。
在一个BFC中,框一个接一个的排列。垂直方向上,框的起点是一个包含块的顶部。两个同级框的垂直距离由margin决定,垂直方向毗邻的块级框的margin会发生折叠。
在一个BFC中,每个框的左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边), 即使存在浮动也是这样(尽管一个框的内容区域会由于浮动而收缩),除非这个框形成了一个新的BFC(这种情况下,框本身由于浮动变得更窄)。
在这里不翻译BFC具体中文怎么读,有翻译成“块级格式化上下文”,想想觉得很别扭。我的理解是,一个BFC提供了一个方形区域,它包裹里面的块框与行内框,决定它们的布局。
形成BFC的方法:
- float:left|right
- position:absolute|fixed
- display:inline-block|table-cell|table-caption
- overflow:hidden|auto|scroll
BFC的作用:
- 情况1:
解决办法(外边距折叠有很多解决办法)之一是为外面的黑色框添加overflow:hidden,使之形成一个BFC。
- 情况2:
解决办法是让未浮动元素形成一个BFC,使之不与浮动元素堆叠。
- 情况3:形成BFC的元素可以清除它内部的浮动,使得高度不“塌陷”。
hasLayout
hasLayout是IE下的一个专有概念(属性),它决定一个元素是否拥有一个布局。它并不是一个CSS属性,所以不能显示的对它设置true或false。一个拥有布局的元素负责它自己及其子元素的尺寸和定位,没有布局的元素由其拥有布局的祖先元素负责。当一个元素拥有布局时,就称它has layout(hasLayout为true)。hasLayout在IE8标准模式中被移除。
hasLayout的作用可以减少IE显示引擎的处理开销。在理想情况下,所有的元素都可以负责自己的尺寸和定位,但这在早期版本的IE中会产生很大的性能问题,所以IE只对一部分元素设置hasLayout。
默认拥有布局的元素有:
html,body,table,tr,th,td,iframe,object, applet,img,hr,input,button,select,textarea,fieldset,legend等。
设置以下属性会使一个元素拥有布局:
- position:absolute
- float:left or right
- display:inline-block
- width:any value other than auto
- height:any value other than auto
- zoom:any value other than normal
- writing-mode:tb-rl
IE7还可以通过一下属性设置hasLayout:
- overflow:hidden or scroll or auto
- overflow-x:hidden or scroll or auto
- overflow-y:hidden or scroll or auto
- min-width:any value other than auto
- max-width:any value other than auto
- min-height:any value other than auto
- max-height:any value other than auto
hasLayout有点类似于BFC,比如在上文BFC中的情景都可以在IE6、7用触发hasLayout的方法解决。IE6、7的很多布局产生的bug(如3px间隙、绝对定位的继承宽度)都可以通过触发hasLayout修复,比较推荐的方法为zoom:1与height:1%,不会破坏已有的样式。
设置有些属性(如float、position、display)会同时形成BFC与触发hasLayout,或者在>=IE7时可以设置overflow同时搞定两者。若只触发(形成)了其中一个,也最好同时触发(形成)另一个,以保证浏览器的兼容。