1.hasLayout
关于IE下的这个私有的东东,以前也研究过,这儿不多说,只说两点:
(1)它是什么:
它决定了元素如何对其内容进行定位和尺寸计算,与其他元素的关系和相互作用,以及对应用还有使用者的影响。
‘Layout’ 可以被某些 CSS property(特性)不可逆的触发,而某些 HTML 元素本身就具有 layout 。
‘Layout’ 在 IE 中可以通过 hasLayout 属性来判断一个元素是否拥有 layout ,如 object.currentStyle.hasLayout 。
‘Layout’ 是 IE 浏览器渲染引擎的一个内部组成部分。在 IE 浏览器中,一个元素要么自己对自身的内容进行组织和计算大小, 要么依赖于包含块来计算尺寸和组织内容。为了协调这两种方式的矛盾,渲染引擎采用了 ‘hasLayout’ 属性,属性值可以为 true 或 false。 当一个元素的 ‘hasLayout’ 属性值为 true 时,我们说这个元素拥有了一个布局(layout),即成功触发hasLayout。
(2)它主要干什么:
IE6/7以及IE8的诡异模式下有许多莫名其妙的bug,当遇到一些摸不着头脑的布局问题时,可以试着触发相关元素的hasLayout,使其为ture,你会发现,许多的问题都与这个属性有关。
下面的元素的hasLayout默认为true:
<html>, <body>
<table>, <tr>, <th>, <td>
<img>
<hr>
<input>, <button>, <select>, <textarea>, <fieldset>, <legend>
<iframe>, <embed>, <object>, <applet>
<marquee>
可触发 hasLayout 的 CSS 特性:
display: inline-block /*ALL*/
height: (除 auto 外任何值) /*仅适用IE6 7*/
width: (除 auto 外任何值) /*仅适用IE6 7*/
float: (left 或 right) /*ALL*/
position: absolute /*ALL*/
writing-mode: tb-rl /*ALL*/
zoom: (除 normal 外任意值) /*仅适用IE6 7*/
IE7 还有一些额外的属性(不完全列表)可以触发 hasLayout :
min-height: (任意值)/*以下适用IE7+*/
min-width: (任意值)
max-height: (除 none 外任意值)
max-width: (除 none 外任意值)
overflow: (除 visible 外任意值,仅用于块级元素)
overflow-x: (除 visible 外任意值,仅用于块级元素)
overflow-y: (除 visible 外任意值,仅用于块级元素)
position: fixed
IE6 以前的版本(也包括 IE6 及以后所有版本的混杂模式,其实这种混杂模式在渲染方面就相当于 IE 5.5), 通过设置任何元素的 ‘width’ 或 ‘height’(非auto)都可以触发 hasLayout ; 但在 IE6 和 IE7 的标准模式中的行内元素上却不行,设置 ‘display:inline-block’ 才可以。(个人觉得这个现在没有什么意义了,IE5.5?还是算了吧,基本找不到了)
2.BFC(Block Formatting Contexts)
非IE浏览器中和hasLayout极其相似的一个属性就是BFC(块格式化上下文)。
(1)它是什么:
BFC是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。
在创建了 BFC的元素中,其子元素会一个接一个地放置。垂直方向上他们的起点是一个包含块的顶部,两个相邻的元素之间的垂直距离取决于 ‘margin’ 特性。在BFC中相邻的块级元素的垂直边距会折叠(collapse)。
在BFC 中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边), 即使存在浮动也是如此(尽管一个元素的内容区域会由于浮动而压缩),除非这个元素也创建了一个新的BFC。
(2)触发方式:
float:(任何值除了none)
overflow:(任何值除了visible)
display:(table-cell/table-caption/inline-block)
position:(任何值除了static/relative)看到了么?触发方式和hasLayout的触发方式挺像的。
3.hasLayout 和 BFC 相比较
3.1 在触发 hasLayout 的元素和创建了 BFC的元素中,浮动元素参与高度的计算.
先来看下面的代码:
<div style="width:300px;">
<div id="container" style="background:#eee">
<span id="span1" style="background:red">我是span行内元素</span>
<div id="div1" style="width:150px; height:50px; background:#999">我是普通流中的块级元素</div>
<div id="div2" style="float:left; background:yellow">我是浮动元素</div>
</div>
</div>
根据 CSS2.1 规范第 10.6.3 部分的高度计算规则,在进行普通流中的块级非替换元素的高度计算时,浮动子元素不参与计算。
所以IE6/7下和标准浏览器下面的效果是一样的,即id为container的容器中不包含浮动的div2。
效果图如下:
但是当我们给id为container的容器加上触发BFC的属性之后(overflow:hidden),可以看到浮动元素参加了高度的运算:
可以预见,IE下面依然是浮动元素不参加高度的运算。
演示文件地址:
触发BFC
而触发IE下的hasLayout,同样可以得到一样的效果:
演示地址:IE下触发haslayout
通过以上的分析与实践,我们得知:
如果不触发标准浏览器下的BFC以及IE6/7下面的haslayout的话,浮动元素是不参加父元素的高度的计算的,显示效果一样,如果只触发haslayout或者BFC的话,则触发的浏览器里面浮动元素参与父元素高度的计算(即父元素包含浮动元素)。所以如果我们要让父元素包含浮动元素并且兼容所有浏览器的话,就得同时触发haslayout与BFC。
3.2 与浮动元素相邻的、触发了 hasLayout 的元素或创建了 BFC 的元素,都不能与浮动元素相互覆盖.
如果浮动元素的两侧有足够的空间放置该元素,则元素会紧邻浮动元素放置,必要时,该元素的宽度将会被压缩。否则它们可 能会定位到浮动元素的下方。
先来看下面的代码:
<div id="container" style="border:2px solid yellow; width:300px; height:150px">
<div id="div1" style="background-color:yellow; width:100px; height:100px; float:left; filter:alpha(opacity=50); opacity: 0.5;">
我是一个浮动元素!
</div>
<div id="div2" style="background-color:green;">
我是一个紧跟浮动元素的普通块级元素!
</div>
</div>
根据 CSS 2.1 9.5 Floats 中的描述,浮动元素会覆盖普通流中的块容器。所以,div2 应该有一部分被 div1 覆盖。
IE浏览器和标准浏览器中的效果如下图所示:
可以清楚的看到,效果是一样的(当然忽略IE6下的3px bug),即都是符合标准的。
但是当我们给普通块级元素加上zoom:1,即触发了IE的haslayout后,ie6/7下的块级元素会拥有布局,不再被浮动元素覆盖。如下:
演示地址:触发IE下的haslayout(float覆盖)
可以预见,标准浏览器下的效果不变,要想得到相同的效果,则需触发起BFC,加上overflow:hidden试试。 Read the rest of this post









