我们都知道浏览器有bug,而IE的bug似乎比大多数浏览器都多。IE的表现与其他浏览器不同的原因之一就是,显示引擎使用一个称为布局(layout)的内部概念。
因为布局是专门针对显示引擎内部工作方式的概念,所以一般情况下不需要了解它。但是,布局问题是许多IE显示bug的根源,所以理解这个概念以及它如何影响CSS对修复bug是有帮助的。
一、什么是haslayout
haslayout是Windows Internet Explorer渲染引擎的一个内部组成部分。在Internet Explorer中,使用布局概念来控制元素的尺寸和定位。在理想情况下,所有元素都控制自己的尺寸和定位。但是,这在IE中会导致很大的性能问题。因此,IE开发团队决定只将布局应用于实际需要它的那些元素,这样就可以充分地减少性能开销。
拥有布局(have layout)的元素负责本身及其子元素的尺寸和定位。如果一个元素没有布局,那么它的尺寸和位置由最近的拥有布局的祖先元素控制。IE显示引擎利用布局概念减少它的处理开销。一个元素要么自己对自身的内容进行计算大小和组织,要么依赖于父元素来计算尺寸和组织内容。
为了调节这两个不同的概念,渲染引擎采用了hasLayout的属性,属性值可以为true或false。当一个元素的 hasLayout属性值为true时,我们说这个元素有一个布局(layout),当一个元素有一个布局时,它负责对自己和可能的子孙元素进行尺寸计算和定位。简单来说,这意味着这个元素需要花更多的代价来维护自身和里面的内容,而不是依赖于祖先元素来完成这些工作。因此,一些元素默认会有一个布局。当我们说一个元素“拥有layout”或“得到layout”,或者说一个元素“has layout”的时候,我们的意思是指它的微软专有属性 hasLayout 被设为了true 。一个“layout元素”可以是一个默认就拥有layout的元素或者是一个通过设置某些CSS属性得到layout 的元素。如果某个HTML元素拥有haslayout属性,那么这个元素的 haslayout的值一定只有true,haslayout为只读属性一旦被触发,就不可逆转。通过IE Developer Toolbar可以查看IE下HTML元素是否拥有haslayout,在IE Developer Toolbar下,拥有haslayout的元素,通常显示为“haslayout = -1”。
二、默认拥有haslayout属性
<html>, <body><table>, <tr>, <th>, <td><img><hr><input>, <button>, <select>, <textarea>, <fieldset>, <legend><iframe>, <embed>, <object>, <applet><marquee>
三、IE下hasLayout布局的触发机制
言归正转,为此,我们要认识hasLayout,了解它,然后才能更好的针对问题找出解决办法。
首先,我们要了解Layout与hasLayout属性是什么?Layout,意为“布局”,是IE/Windows下的特有概念,它决定了元素如何对其内容进行定位和尺寸计算,与其他元素的关系和相互作用,以及对应用还有使用者的影响。hasLayout为只读属性,对本身不具有Layout的元素,如果其Layout被动触发后是不可逆的。hasLayout,是IE渲染引擎的一个内部组成部分。在IE中,一个元素计算大小和组织内容,要么对自身的内容进行计算大小和组织内容,要么依赖于父元素来计算尺寸和组织内容。为了调节这两个不同的概念,渲染引擎采用了hasLayout的属性,属性值可以为true或false。当一个元素的 hasLayout属性值为true时,我们说这个元素有一个布局(Layout)。
据不完全统计,默认具有haslyout的HTML标签元素有:<table>、<td>、<body>、<img>、<hr>、<input>、<select>、<textarea>、<button>、<iframe>、<embed>、<object> <applet>、<marquee>、< html>、< tr>、< th>、<fieldset>、< frameset>、<frame> 等。当网页在IE中有异常表现时,可以首先通过尝试激发haslayout来确定是否为当前容器的Layout没有被激发造成。接着,我们看如何来激发元素的hasLayout属性。以下是“寂寞贱客”1、通过设置CSS能够获得的haslayout的属性有:display: inline-block;、height: (任何值除了auto);、float: (left或right);、position: absolute;、 width: (任何值除了auto);、writing-mode: tb-rl;、zoom: (除normal外任意值);、 min-height: (任意值);、 max-height: (除none外任意值);、min-width: (任意值);、max-width: (除none外任意值);、overflow: (除visible外任意值);、overflow-x: (除visible外任意值);、overflow-y: (除visible外任意值);、 position: fixed;(未完全统计)。2、对于内联元素(默认即为内联的元素,如span,或display:inline; 的元素),width和height只在IE5.x下和IE6或更新版本的quirks模式下触发hasLayout。而对于IE6,如果浏览器运行于标准兼容模式(具有Doctype的模式)下,内联元素会忽略width或height属性,所以设置width或height不能在此种情况下令该元素具有layout。3、zoom总是可以触发hasLayout,但是在IE5.0中不支持。4、对IE6及更早版本来说,常用的方法被称为霍莉破解(Holly hack),即设定这个元素的height:1%;。需要注意的是,当这个元素的overflow属性为visible时,这个方法就失效了。曾经流行使用这种方法的时候,还没有出现IE7,而height属性在IE6下其实是按照"min-height"来解析的,所以只要对IE6进行hack,"* html{height:1%}"就可以触发hasLayout,同时又不产生副作用。后来出现的IE7仍然存在很多hasLayout的问题,但IE7已经能够正确识别height属性了,“height:1%”的方法已经不再适用了。5、对IE7来说,最好的方法是设置元素的最小高度为0px(min-height0;)。
相关文章:
1. Flutter刷新组件RefreshIndicator自定义样式demo2. requestAnimationFrame使用示例详解3. 基于JavaScript实现图片裁剪功能4. React优雅的封装SvgIcon组件示例5. uniapp自定义验证码输入框并隐藏光标6. 详解JavaScript中原始数据类型Symbol的使用7. JavaScript深拷贝方法structuredClone使用8. uniapp 手机验证码输入框实现代码(随机数、倒计时、隐藏手机号码中间四位)可以直接使用9. 使用Node.js实现Clean Architecture方法示例详解10. 怎么让div+css兼容ie6ie7ie8ie9和FireFoxChrome等浏览器