haslayout 的概念
haslayout 是Windows Internet Explorer渲染引擎的一个内部组成部分。在InternetExplorer中,一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元素来计算尺寸和组织内容。为了调节这两个不同的概念,渲染引擎采用了 hasLayout 的属性,属性值可以为true或false。当一个元素的 hasLayout属性值为true时,我们说这个元素有一个布局(layout)。
要想更好的理解 css, 尤其是 IE 下对 css 的渲染,haslayout 是一个非常有必要彻底弄清楚的概念。大多IE下的显示错误,就是源于 haslayout。如果它设置成了true,它就不得不去渲染它自己,因此元素不得不扩展去包含它的流出的内容。例如浮动或者很长很长的没有截断的单词,如果haslayout没有被设置成true,那么元素得依靠某个祖先元素来渲染它。这就是很多的ie bugs诞生的地方。
如何激发 haslayout?
大部分的 IE 显示错误,都可以通过激发元素的 haslayout 属性来修正。可以通过设置 css 尺寸属性(width/height)等来激发元素的 haslayout,使其“拥有布局”。如下所示,通过设置以下 css 属性即可。
* display: inline-block
* height: (任何值除了auto)
* float: (left 或 right)
* position: absolute
* (任何值除了auto)
* writing-mode: tb-rl
* zoom: (除 normal 外任意值)
Internet Explorer 7 还有一些额外的属性(不完全列表):
* min-height: (任意值)
* max-height: (除 none 外任意值)
* min- (任意值)
* max- (除 none 外任意值)
* overflow: (除 visible 外任意值)
* overflow-x: (除 visible 外任意值)
* overflow-y: (除 visible 外任意值)
* position: fixed
其中 overflow-x 和 overflow-y 是 css3 盒模型中的属性,目前还未被浏览器广泛支持。
对于内联元素(默认即为内联的元素,如 span,或 display:inline; 的元素),
width 和 height 只在 IE5.x 下和 IE6 或更新版本的 quirks 模式下触发 hasLayout 。而对于IE6,如果浏览器运行于标准兼容模式下,内联元素会忽略 width 或 height 属性,所以设置 width 或 height不能在此种情况下令该元素具有 layout。
zoom 总是可以触发 hasLayout,但是在 IE5.0 中不支持。
BFC 的概念
BFC,块格式化上下文( Block formatting context ),是指初始化块级元素定义的环境。在CSS中,元素定义的环境有两种,一种是块格式化上下文( Block formatting context ),另一种是行内格式化上下文( Inline formatting context )。其中我们使用比较多的是块级可视化上下文,CSS3草案中将之称为“flow root”,但我们仍习惯叫BFC,其的触发条件如下:
* 浮动元素(float除了none)
* 绝对定位元素(absolute/fixed)
* 设置了’display’ 属性为 “inline-block”,”table-cell”, “table-caption” 的元素
* 设置了overflow 非 “visible”的元素
使用BFC和hasLayout应该注意的问题
1、overflow:hidden触发BFC的同时,也能触发ie7的hasLayout,但overflow:hidden是ie7新添加的触发hasLayout的新属性,ie6并不支持,因此要兼容ie6必须加_zoom:1;
2、浮动和不浮动元素间,ie6会有3px的间隙,这是ie6的bug,解决方法是:若浮动元素是左浮动,则给左浮动元素加margin-right:-3px;若浮动元素是右浮动,则给右浮动元素加margin-left:-3px;
3、不浮动元素的左间距margin-left值若小于左浮动的元素宽度则不会生效,同理,不浮动元素的右间距margin-right值若小于右浮动的元素宽度也不会生效!这个跟没触发bfc或ie的haslayout时,不浮动元素的左右间距取值生效情况是保持一致的;
4、在实际运用中,浮动元素跟不浮动元素间都会加入左右间距控制,考虑到浮动元素可能会加入当前流行的多设备兼容的media query ,浮动元素的宽度会随着媒体查询的设置的css变化而变化,而不浮动元素的margin-left/right值能否生效又是跟浮动元素的宽度关联的,这时在不浮动元素上加入margin-left/right值来控制元素的间距,显示麻烦,不好掌控,推荐给浮动和不浮动元素间加间距的做法是:直接给浮动元素加margin值,而不是给不浮动元素加margin值,唯一要注意的是给浮动元素加margin值时,应该考虑到ie6浮动和不浮动元素间的3px bug,即ie下浮动元素margin-left/right正确值应该比其它浏览器的对应值小3px才能保持与其它浏览器显示效果一致。