[译]IE6终极备忘:修复IE6下 25+ Bugs 2010年01月08日 | HTML/CSS, JavaScript 去年就想将IE的bug系统地整理下,但一直都很忙没有完成,看到这篇E文后,我毫不犹豫的放下了手中的工作将之翻译出来。 由于是第一次译文,所以错误在所难免,欢迎大家批评指正。 原文:Ultimate IE6 Cheatsheet: How To Fix 25+ Internet Explorer 6 Bugs 翻译:http://www.vfresh.org/w3c/727(译文对原文进行了补充) 对IE6最好的策略就是不去兼容它。 好吧,我知道你的难处,你不得不去兼容IE6这个狗血的浏览器,因此不得不在兼容IE6上花费很多时间。对此,我颇有同感,让我来帮助你吧。 我不会象许多文章那样让你去抵制IE6,这并不会帮助到你(迫不得已时)去兼容IE6;因为IE6依旧占有一定的市场份额,你无法放弃IE6。本文将帮助你来解决这个难题。 我查阅过很多资料来摘录这些解决方案(有些是我自己提供的),现在我做成手册提供给大家搞定IE6这个家伙。我尽可能的提供了最优解决方案而不是一些hacks,并且提供了一些相关的资料。如果你发现有更好的方法或者本文有错误,请联系我。 【目录】 〖策略〗 在讨论IE6的BUG及如何修复之前,有必要先讲一些策略去避免这些恼人的问题——正所谓防患于未然 。 IE6 市场占有率 做一个简洁的设计 使用合适的文档申明(doctype) 验证你的代码 先对标准浏览器进行兼容 渐进增强(Progressive Enhancement) 使用自己的预设样式(CSS Reset) 使用JavaScript框架 使用JavaScript模拟标准浏览器 如何在IE下调试页面 〖对IE6单独兼容〗 兼容IE6的第一步就是单独对IE进行兼容,你针对IE6所写的代码只影响IE6。 使用IE特有条件注释 使用CSS选择器区分开IE6 使用JavaScript区分开IE6 〖图片〗 PNG半透明图片 IE6下的圆角 背景闪烁问题 〖布局〗 解决IE6布局方面的BUG非常的恼人!特别是在实现一个精美的设计稿时。 理解 hasLayout IE6 盒模型 最小高度 最大高度 100% 高度 最小宽度 最大宽度 双边距Bug 清除浮动 浮动层错位 躲猫猫bug(The Guillotine Bug) 绝对定位元素的1像素间距bug 3像素间距bug IE下z-index的bug Overflow Bug 〖列表〗 横向列表宽度bug 列表阶梯bug 列表间隙bug 〖行为〗 ie6有着一些行为方面的BUG,究其原因是IE6版本太老了,不能完好地支持CSS2更不支持CSS3,而且微软固执的使用了其私有方法。 IE6中的:hover 在IE浏览其中使用Canvas标签 IE6调整窗口大小的 Bug 〖JavaScript〗 IE6有着数不尽的JavaScript bug,这里我不会讲解每一个IE6下JavaScript的bug,只摘取其中几个普遍的问题来讨论。 异常: Expected Identifier, String, Or Number IE中JavaScript内存泄露 〖其他〗 文本重复Bug 收藏夹图标 IE6中GZip文件Bug 〖相关资源〗 〖策略〗 在讨论IE6的BUG及如何修复之前,有必要讲叙一些策略去避免这些恼人的问题——正所谓防患于未然 。 目录 | 顶部 IE6 市场占有率 据Market Share统计,目前(2009年8月)IE6 的市场占有率为25.25%,但是其他地方的统计明显要低,为18.1%;尽管统计结果不同,但都呈现出了下降的趋势(翻译此文时,淘宝的IE6用户已从70%跌破至69%)。但是最重要的,还是你自己网站的统计数据。如果你对你的网站进行了流量分析,那么IE6的占有率是否值得你去针对IE6进行开发?这需要你自己去权衡。 如果你网站绝大部分访问者不使用IE6并且不付费给你,那么你不必特意区针对IE6做兼容,从而节省时间、精力及资金。 目录 | 顶部 做一个简洁的设计 在做设计的同时考虑代码的实现,可以避免一些布局上的问题。再复杂的设计稿也能用简洁的代码实现,如果你使用了过于繁冗的标签,那么你需要重新修缮设计稿。 如果你有丰富的开发经历,攻克过很多种布局难题,记录下你的解决方案,在以后碰到相同问题时可以提高开发效率。 目录 | 顶部 使用合适的文档申明(doctype) 使用一个错误的文档声明会触发quirks mode(怪异模式),正确的文档声明可以保证你的页面在所有浏览器下保持一致的效果。使用其中的一个文档申明:HTML 5, HTML 4.01 Strict, HTML 4.01 Frameset, HTML 4.01 Transitional, XHTML 1.0 Strict, XHTML 1.0 Frameset, XHTML 1.0 Transitional, or XHTML 1.1 HTML 5 html运行 HTML 4.01 Strict html运行 HTML 4.01 Frameset html运行 HTML 4.01 Transitional html运行 XHTML 1.0 Strict html运行 XHTML 1.0 Frameset html运行 XHTML 1.0 Transitional html运行 XHTML 1.1 html运行 目录 | 顶部 验证你的代码 我曾听说过有些人认为校验代码没有任何实用价值,但我不这么认为。校验仅仅只需花费一点点时间,而且将受益于所有浏览器而非仅仅IE6;验证确保了向后兼容并且易于维护。至少也得验证XHTML!唯一可以忽略验证的情况是在你打算使用CSS3时。 你可以使用w3提供的工具验证XHTML/验证CSS 目录 | 顶部 先对标准浏览器进行兼容 在写代码的过程中,一开始在标准浏览器中测试(如 Firefox, Opera, Chrome等),然后再去测试非标准浏览器(如IE6/IE7),因为这些标准浏览器都遵循w3c标准,大多的处理方式都相同。你可以分开来单独去兼容“特别”的IE浏览器,这样做能规范你的代码,你将会因此拥有扎实的基础;而且如果你不再需要兼容这些非标准浏览器,你可以一次性删除这些修复兼容性代码。 目录 | 顶部 渐进增强(Progressive Enhancement) 渐进增强(Progressive Enhancement)是为了确保没有页面特效后基本功能也是可用的。简单来讲,渐进增强是指在确保页面在禁用JavaScript后能正常运作后,再对页面添加各种特效(JavaScript动画、Ajax异步等等)。我们同样可以运用“渐进增强”原则来使用CSS3(或者一些CSS2)、HTML5以及其他IE6所不支持的web规范。 某些情况下,是无法让所有用户在任何浏览器下都完全一模一样,特别是那些使用IE6的用户。运用渐进增强策略,可以保证让那些用户至少使用到你网站(或网络应用)的基本功能。 更多渐进增强的资料: 理解渐进增强(译文) Understanding Progressive Enhancement Progressive Enhancement With CSS Progressive Enhancement: What It Is, And How To Use It? Graceful Degradation vs. Progressive Enhancement Pragmatic Progressive Enhancement – Why You Should Bother With It 目录 | 顶部 使用自己的预设样式(CSS Reset) 每个浏览器都有各自不同的预设样式,在你的样式表之前使用预设样式(CSS Reset)可以避免在之后编写冗长的浏览器兼容样式。在网上有很多CSS Reset可供参考。 简单CSS Reset示例: css body,div,ul,ol,li,h1,h2,h3,h4,h5,h6,form,fieldset,input,textarea,p,th,td {margin:0;padding:0;} 一些可供参考的CSS Resets: YUI CSS Reset Eric Meyer’s Reset Reloaded KISSY CSS Reset 目录 | 顶部 使用JavaScript框架 如果你的网站使用了较多的JavaScript特效,建议使用JavaScript框架。大部分的js框架都兼容了包括IE6在内的各种浏览器。可选的框架有很多,但一般能用一种框架实现的效果一定可以用另外一种框架实现,所以你可以根据个人喜好来选择合适的框架。 以下是一些常用的JavaScript框架: MooTools jQuery ProtoType with Scriptaculous Dojo Ext JS 强烈推荐实用MooTools,但如果你是入门者,还是建议使用jQuery。 目录 | 顶部 使用JavaScript模拟标准浏览器 现在有一些JavaScript来使IE模拟标准浏览器,如果你有较高比例的用户使用IE6并且开启了JavaScript,可以考虑使用Dean Edwards的IE7或者类似的脚本。 译者注:不建议使用这些脚本,因为这些“模拟”的实现往往会消耗大量的资源,IE本来就够烂了。 目录 | 顶部 如何在IE下调试页面 在IE下调试页面很麻烦,Firefox下的扩展程序Firebug和Web Developer Toolbar都是很好用的工具,如果你想在IE或其他浏览器上使用firebug,可以用Firebug Lite。 在IE下有两种最好的调试方法:IE Collection和IETester,并且都是免费的(虽然有一点点缺陷)。IETester的开发者也提供了DebugBar这款IE插件免费供个人使用,但商业用户只可试用60天。 目录 | 顶部 〖对IE6单独兼容〗 兼容IE6的第一步就是单独对IE进行兼容,你针对IE6所写的代码只影响IE6;有几种方法可以区分开IE6:IE特有条件注释、CSS选择器、JavaScript,我们将逐一讨论。 目录 | 顶部 使用IE特有条件注释 微软给IE添加了条件注释以区分不同版本,任何东西都可以塞进条件注释里:标签、JavaScript、js文件、css、内联样式。可以使用条件注释来针对某一个IE浏览器版本来编写代码。 规则如下:(译注:可参考IE 特有注释(hack)) html运行
这段文字会在所有浏览器显示
这段文字会在所有浏览器显示
使用条件注释加载css的好处是这些样式是独立于其他css文件的,因此不会在编写兼容代码时弄得一团糟;而且当IE6的市场份额降低到不需要兼容时,可以快速的清理掉。 使用条件注释的唯一缺点是在IE浏览器下会增加额外的HTTP请求数,所以需要权衡是否这样做。但我不建议使用条件注释加载外部js文件,因为js文件会造成阻滞,在js未加载完之前其余文件都不会被加载;对于js请使用JavaScript程序来区分浏览器而非条件注释。 目录 | 顶部 使用CSS选择器区分开IE6 如果你不打算使用条件注释,CSS选择器是另外一个区分开IE6的办法,IE6不支持子选择器;先针对IE6使用常规申明CSS选择器,然后再用子选择器针对IE7+及其他浏览器。 示例: html运行
这个方法的缺点是容易把样式表弄得一团糟,所以一定要写好注释说明。 在示例中,针对IE6写的样式在其他浏览器中也会执行,但(标准浏览器中)之后的子选择器覆盖了之前的申明,而IE6不支持子选择器所以忽略了它。 扩展阅读: CSS Browser Compatibility Chart Master Browser Compatibility Chart 目录 | 顶部 使用JavaScript区分开IE6 如果你想要使用JavaScript区分开IE6,请看示例: javascript //原生JavaScript if(typeof document.body.style.maxHeight === "undefined") { alert('IE6 Detected'); } //MooTools(框架) if (Browser.Engine.trident4) { alert('IE6 Detected'); } //jQuery(框架) if (($.browser.msie) && ($.browser.version == "6.0")){ alert('IE6 Detected'); } 扩展阅读: Quirksmode’s Browser Object MooTools’ Browser Object jQuery’s support utility 目录 | 顶部 〖图片〗 目录 | 顶部 PNG半透明图片 有很多JavaScript解决方案来修复IE6使用PNG-24图片,但除了Twin Helix’s IE5.5+ PNG Alpha Fix都不支持CSS sprites。 另外一个办法是使用IE特有的滤镜,可阅读Aaron Baxter的博客。或译者的《ie5+ PNG Fix》 JavaScript方式修复IE6 PNG MooTools’ FixPNG jQuery PNG fix IE PNG Fix by Twin Helix TweakPNG DD_belatedPNG 目录 | 顶部 IE6下的圆角 可以详细阅读CSS 圆角菜单。 目录 | 顶部 背景闪烁问题 如果你给链接、按钮用CSS sprites作为背景,你可能会发现在IE6下会有背景图闪烁的现象。造成这个的原因是由于IE6没有将背景图缓存,每次触发hover的时候都会重新加载,可以用JavaScript设置IE6缓存这些图片: javascript document.execCommand("BackgroundImageCache",false,true); 其他解决方法: Minimize Flickering CSS Background Images in IE6 目录 | 顶部 〖布局〗 解决IE6布局方面的BUG非常的恼人!特别是在实现一个精美的设计稿时。 目录 | 顶部 理解 hasLayout 许多IE6下的Bug及渲染问题都可以归于微软的私有概念hasLayout。简要的说,在给元素定义具体的尺寸(如height或width)就会触发hasLayout,在IE6下缺失或触发hasLayout会导致一些bug。 扩展阅读: 《On having layout》(译文) “HasLayout” Overview from Microsoft hasLayout CSS Bugs IE6 盒模型 如果怪异模式(quirks mode)在IE6中启用,IE6将会使用微软旧版的盒模型:width是元素的实际宽度,内容宽度 = width – (margin-left + margin-right + padding-left + padding-right + border-left-width + border-right-width)。最好的办法是申明正确的文档类型以避免触发怪异模式,或者避免给有border或padding的元素定义width属性。当然你也可以考虑使用条件注释。 扩展阅读: IE CSS Tricks That Will Get You Every Time Internet Explorer And The CSS Box Model Internet Explorer Box Model Bug 目录 | 顶部 最小高度 IE6 不支持min-height属性,但它却认为height就是最小高度。感谢Dustin Diaz提供了一个很好的方法:使用!important,ie6会忽视它但其余浏览器不会。 注:IE6在同一个声明语句中(即一个综括号{})的属性定义,后面的总是会覆盖前面的,所以下例中后面的height覆盖掉了前面定义的important height css /* 所有浏览器 */ #container {min-height:200px; height:auto !important; height:200px;} 另一个方法是使用CSS 选择器: css /* 仅IE6 */ #container {min-height:200px; height:200px;} /* 其他浏览器 */ html>body #container { height:auto;} 目录 | 顶部 最大高度 非常遗憾,在IE6下实现max-height只能使用IE特有滤镜,或者可以使用JavaScript实现。我个人更建议使用JavaScript来解决,因为IE滤镜会消耗大量资源甚至会使浏览器崩溃,而且禁用JavaScript后这两种方法都无法生效。 JavaScript javascript //直接使用ID来改变元素的最大高度 var container = document.getElementById('container'); container.style.height = (container.scrollHeight > 199) ? "200px" : "auto"; //写成函数来运行 function setMaxHeight(elementId, height){ var container = document.getElementById(elementId); container.style.height = (container.scrollHeight > (height - 1)) ? height + "px" : "auto"; } //函数示例 setMaxHeight('container1', 200); setMaxHeight('container2', 500); 目录 | 顶部 100% 高度 在IE6下,如果要给元素定义100%高度,必须要明确定义它的父级元素的高度,如果你需要给元素定义满屏的高度,就得先给html和body定义height:100%;。 css /* 给child元素定义100%高度(IE6)*/ #parent {height:500px;} #child {height:100%;} /* 定义满屏高度(IE6)*/ html, body {height:100%;} #fullLength {height:100%;} 目录 | 顶部 最小宽度 同max-height和max-width一样,IE6也不支持min-width。有2个方法实现最小宽度,使用额外的标签、使用JavaScript。 javascript //直接使用ID来改变元素的最小宽度 var container = document.getElementById('container'); container.style.width = (container.clientWidth < width) ? "500px" : "auto"; //写成函数来运行 function setMinWidth(elementId, width){ var container = document.getElementById(elementId); container.style.width = (container.clientWidth < width) ? width + "px" : "auto"; } //函数示例 setMinWidth('container1', 200); setMinWidth('container2', 500); 目录 | 顶部 最大宽度 只能使用JavaScript。 javascript //直接使用ID来改变元素的最大宽度 var container = document.getElementById(elementId); container.style.width = (container.clientWidth > (width - 1)) ? width + "px" : "auto"; //写成函数来运行 function setMaxWidth(elementId, width){ var container = document.getElementById(elementId); container.style.width = (container.clientWidth > (width - 1)) ? width + "px" : "auto"; } //函数示例 setMaxWidth('container1', 200); setMaxWidth('container2', 500); 目录 | 顶部 双边距Bug 当元素浮动时,IE6会错误的把浮动方向的margin值双倍计算。Steve Clason给出了解决方法:给元素添加display:inline; css /*IE6下将产生双倍边距*/ .floatedEl {float:left; margin-left:100px;} /*修正*/ .floatedEl {float:left; margin-left:100px; display:inline;} 目录 | 顶部 清除浮动 如果你想用div(或其他容器)包裹一个浮动的元素,你会发现必须给div(容器)定义明确的height、width、overflow之中一个属性(除了auto值)才能将浮动元素严实地包裹。 示例: html运行
css #container {border:1px solid #333; overflow:auto; height:100%;} #floated1 {float:left; height:300px; width:200px; background:#00F;} #floated2 {float:right; height:400px; width:200px; background:#F0F;} 译者常用的方式: css #container {zoom:1;} /* ie浏览器 */ #container:after{content:"\0020";display:block;height:0;clear:both;} /*标准浏览器*/ 扩展阅读: 《清理浮动的全家》 Clearing Floats Simple Clearing of Floats 目录 | 顶部 浮动层错位 当内容超出外包容器定义的宽度时会导致浮动层错位问题。在Firefox、IE7及其他标准浏览器里,超出的内容仅仅只是超出边缘;但在IE6中容器会忽视定义的width值,宽度会错误地随内容宽度增长而增长。如果在这个浮动元素之后还跟着一个浮动元素,那么就会导致错位问题。 浮动层错位问题在IE6下没有真正让人满意的解决方法,虽然可以使用overflow:hidden;或overflow:scroll;来修正,但hidden容易导致其他一些问题,scroll会破坏设计;JavaScript也没法很好地解决这个问题。所以我的建议是一定要避免这个问题发生,使用一个固定的布局或者控制好内容的宽度。 扩展阅读 Float Drop – floated elements drop below their expected position Internet Explorer 6 and the Expanding Box Problem 目录 | 顶部 躲猫猫bug 在IE6和IE7下,躲猫猫bug是一个非常恼人的问题。一个撑破了容器的浮动元素,如果在他之后有不浮动的内容,并且有一些定义了:hover的链接,当鼠标移到那些链接上时,在IE6下就会触发躲猫猫。 点此查看bug示例页 头大了吧!但别担心,well-documented提供了详细的解决方法。 不管为何会触发这个问题,解决方法很简单: 在(那个未浮动的)内容之后添加一个
触发包含了这些链接的容器的hasLayout,一个简单的方法就是给其定义height:1%; 扩展阅读: IE hasLayout and the return of the Guillotine bug 目录 | 顶部 绝对定位元素的1像素间距bug IE6下的这个错误是由于进位处理误差造成(IE7已修复),当绝对定位元素的父元素高或宽为奇数时,bottom和right会产生错误。唯一的解决办法就是给父元素定义明确的高宽值,但对于液态布局没有完美的解决方法。Paul O’Brien有关这个bug有一篇文章来讲解。 扩展阅读: IE6 绝对定位元素的 1px 间距 bug 目录 | 顶部 3像素间距bug 在IE6中,当文本(或无浮动元素)跟在一个浮动的元素之后,文本和这个浮动元素之间会多出3像素的间隔,Stu Nichols有一个非常好的解决方法。 译注:可运行下面代码来查看作者提供的修复方法 html运行
目录 | 顶部 IE下z-index的bug 在IE浏览器中,定位元素的z-index层级是相对于各自的父级容器,所以会导致z-index出现错误的表现。解决方法是给其父级元素定义z-index,有些情况下还需要定义position:relative 扩展阅读: z-index在IE中的迷惑 无法冲破的等级 Squish The Internet Explorer z-index Bug 目录 | 顶部 Overflow Bug 在IE6/7中,overflow无法正确的隐藏有相对定位position:relative;的子元素,如下例: html运行
解决方法就是给外包容器.wrap加上position:relative;。 目录 | 顶部 〖列表问题〗 最为特别的IE许多bug都会影响到列表,这里例举了一些示例。 目录 | 顶部 横向列表宽度bug 如果你使用float:left;把横向摆列,并且内包含的
(或其他)触发了hasLayout,在IE6下就会有错误的表现: html运行
解决方法很简单,只需要给
定义同样的float:left;即可。 目录 | 顶部 列表阶梯bug bug示例: html运行
列表阶梯bug通常会在给的子元素