about haslayout of ie6 and ie7

什么是haslayout

layout是windows ie的一个私有概念,它决定了元素如何对其内容定位和尺寸计算,以及与其他元素的关系和相互作用。当一个元素“拥有布局”时,它会负责本身及其子元素的尺寸和定位。而如果一个元素“没有拥有布局”,那么它的尺寸和位置由最近的拥有布局的祖先元素控制。

必须说明的是,ie8及以上浏览器使用了全新的显示引擎,已经不在使用haslayout属性,因此文中提到的haslayout属性只针对ie6和ie7。

为什么会有haslayout

理论上说,每个元素都应该控制自己的尺寸和定位,即每个元素都应该“拥有布局”,当然这只是理想状态。而对于早期的ie显示引擎来说,如果所有元素都“拥有布局”的话,会导致很大的性能问题。因此ie开发团队决定使用布局概念来减少浏览器的性能开销,即只将布局应用于实际需要的那些元素,所以便出现了“拥有布局”和“没有拥有布局”两种情况。

默认情况下拥有布局的元素

body and html (in standards mode)table, tr, th, tdimghrinput, button, file, select, textarea, fieldsetmarqueeframeset, frame, iframeobjects, applets, embed

查看和触发haslayout

haslayout是windows ie私有的,而且它不是css属性,我们无法通过css显式的设置元素的haslayout。但我们可以通过javascript来查看一个元素是否拥有布局:

<div id="div1">这是一个div</div>;
var div1 = document.getElementById('div1');console.log(div1.currentStyle.hasLayout);// false

如果元素拥有布局,obj.currentStyle.hasLayout就会返回true,否则返回false。hasLayout是一个只读属性,所以也无法通过javascript进行设置。

ie6中可以触发元素haslayout的属性

float: left或rightdisplay: inline-blockposition: absolutewidth: 除auto外任何值height: 除auto外任何值zoom: 处normal外任何值writing-mode: tb-rl

ie7中可以触发元素的haslayout的属性

min-height: 任意值min-width: 任意值max-height: 除none 外任意值max-width: 除none 外任意值overflow: 除visible外任意值,仅用于块级元素overflow-x: 除visible 外任意值,仅用于块级元素overflow-y: 除visible 外任意值,仅用于块级元素position: fixed

hasLayout测试

如果在ie6/ie7中发生了一些与标准浏览器不一样的渲染行为,如内容出现错位甚至完全不可见。可以为元素设置一个触发haslayout的属性如{zoom: 1}后,看看之前的问题是否已经消失,这样就可以判断是否是因为haslayout造成的问题了。

haslayout引起的bug及解决方法

  1. ie6中可以使用{zoom: 1}或者{height: 1%}1来触发。
  2. ie7中可以使用{min-height: 0}来触发haslayout,这个技术是无害的,因为0本来就是这个属性的初始值,而且没有必要对其他浏览器隐藏这个属性。

重置hasLayout

在另一条规则中重设以下属性为默认值将重置(或撤销)hasLayout:

width, height (设为"auto")max-width, max-height (设为"none")(在ie7中)position (设为"static")float (设为"none")overflow (设为"visible")(在ie7中)zoom (设为"normal")writing-mode (从"tb-rl"设为"lr-t)

有些属性则不能重置haslayout,也就是说设置haslayout这个操作有时是不可逆的。如:

{display: inline-block设置display属性导致haslayout为true之后,就算在一条独立的规则中覆盖这个属性为blockinline,haslayout这个标志位也不会被重置为false。

mid-widthmid-height设为它们的默认值0,仍然会赋予haslayout,但是ie7却可以接受一个不合法的属性auto来重置haslayout。

Block Formatting Contexts(BFC)

ie有它自己的haslayout属性,那么非ie浏览器呢?非IE浏览器采用的就是BFC(块格式化上下文)。

BFC概念说明

BFC是W3C CSS 2.1规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。

在创建了BFC的元素中,其子元素会一个接一个地放置。垂直方向上他们的起点是一个包含块的顶部,两个相邻的元素之间的垂直距离取决于margin特性。在BFC中相邻的块级元素的垂直边距会折叠(collapse)。

在BFC中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边),即使存在浮动也是如此(尽管一个元素的内容区域会由于浮动而压缩),除非这个元素也创建了一个新的BFC。

在CSS3中,对这个概念做了改动:http://www.w3.org/TR/css3-box/#block-level0CSS3中,将BFC叫做`low root`。

BFC触发方式

float: (任何值除了none)overflow:(任何值除了visible)display: (table-cell/table-caption/inline-block)position: (任何值除了static/relative)

References

  1. http://www.w3.org/TR/CSS21/visuren.html#block-formatting
  2. http://www.smallni.com/haslayout-block-formatting-contexts/
  3. http://riny.net/2013/haslayout/
  4. http://adamghost.com/2009/03/ie-has-layout-and-bugs/
  5. The Internet Explorer hasLayout Property
  6. Cascading Style Sheets - DOM Style APIs - hasLayout property
  7. "HasLayout" Overview
  8. 9 Most Common IE Bugs and How to Fix Them