前言
首先为什么要有兼容这个问题?
因为市场上有各个不同的浏览器,基于不同的内核,渲染机制和效果也没有统一.作为Web开发者,我们不能限定使用者必须使用哪一种浏览器,所以如果不想放弃一部分客户,那么就要让产品在大多数乃至全部浏览器上都可以有一个相对好的浏览体验.
市场的目前主流的浏览器内核,我之前写过一篇博客去介绍<浏览器内核-基本常识>,不了解的朋友建议先去看一看,5分钟有个了解足以.
我们一般提到的兼容都是IE和Firefox,Chrome的对立,也即是IE和非IE的效果统一.通常IE上是实现不了某效果或者存在Bug,所以我建议在Chrome或者Firefox上开发,然后往IE上适配.当然这只是我个人建议,具体还看大家自己怎么操作.另外一个问题就是IE版本的问题,中国因为特殊的环境因素,IE6都还有着很大的市场份额,更勿论IE8了.而IE是在IE9以后才逐步遵循W3C标准,所以好多TX一谈起兼容IE6就脑袋疼,这里就看具体问题了,不过我个人的观念是兼容到IE8,IE6,7尽量说服客户更新版本.不然终归无法完美兼容,体验上还会差很多.总之一句话,不管是解决兼容也好,优化也好,都是为了给使用者带来更好的用户体验,为此我们应该尽各种努力.
Javascript兼容
日常我们的工作中,对于Javascript的兼容我们注意的不多,这要感谢各个Javascript类库,尤其是jQuery.它帮我们解决了很多,甚至近乎所用的常用的Javascript会涉及到的有关兼容的问题.这里我只挑出那些比较常见的,我们工作中会遇到的兼容问题来说一下.
一. 操作样式
(1) CSS属性名与Javascript保留字相同
Javascript如果访问一个元素,操作它的CSS样式,通常可以直接Object.style.Attribute这么写.但是float,for,class这些CSS属性和Javascript的保留字名字相同.所以不同浏览器中就有各自对应的名字,这里以float和class为例.
在IE中:
document.getElementById("d1").style.styleFloat = "right"; document.getElementById("d1").setAttribute("class","cname");
在Firefox,Chrome中:
document.getElementById("d1").style.cssFloat = "right";
//在最新的Chrome版本中,可以直接设置setAttribute("class","cname");这里的className针对是旧版本的Chrome以及Firefox. document.getElementById("d1").setAttribute("className","cname"); //或者直接document.getElementById("d1").className = "cname";这是没问题的.如果要兼容处理,可以通过document.all判断是否是IE浏览器,然后分别写:
<html> <head> <style> .cname { background:red; } </style> </head> <body> <div id="d1" style="height:100px;width:100px;border:solid 1px red"></div> </body> <script> if(document.all){ document.getElementById("d1").style.styleFloat = "right"; document.getElementById("d1").className = "cname"; }else{ document.getElementById("d1").style.cssFloat = "right"; document.getElementById("d1").className = "cname"; } </script> </html>
(2) 高度赋值
如果想将一个元素的高度设为另一个元素的高度.通常可以这么写: Object.style.height = Obj.height;;类似的语句在非IE下是不好用的,如果需要兼容可以这么写: Object.style.height = Obj.height + "px";
二. 事件处理.
在监听事件,以及事件流的冒泡,捕获传播上,IE浏览器和非IE浏览器都是有着各自的不同的,这个我在前面的一篇博客内<浏览器中关于事件的那点事儿>中有详细的介绍,这里不在重复,有兴趣可以链接去看看.这里仅补充一点,那就是event对象,在IE中是存在于window顶级对象下的,可以直接通过window.event获得.而在非IE浏览器下,它是事件触发的对象函数,需要参数带入的.IE中event指向e.srcElement,非IE下指向e.target.
三. DOM操作
Javascript最大的作用之一就是操作DOM,对于DOM的操作无外乎访问,修改和删除.
(1) parentNode替代parentElement
IE中支持parentNode和parentElement两种方式获取父节点,但是在标准浏览器中不支持parentElement.所以对于父节点的获取,要使用parentNode.
(2) removeNode()和removeChild()
删除节点与添加不同的是,appendNode在IE和标准浏览器下都可以用,但是removeNode()在标准浏览器下是不可以的,所以这里不推荐使用.可以先获取父节点,然后removeChild(child).
(3) childNodes遍历节点
有时候我们可能需要遍历一个节点下所有的子节点,此时有一个childNodes属性可以使用.但是在IE和标准浏览器的含义却不相同.所以对于节点遍历可以通过document.getElementByTagName()或者通过jQuery规避.
四. 其他
(1) Ajax的XMLHttpRequest对象创建
在IE和非IE浏览器中,原生Javascript使用new ActiveXObject()创建XHR对象的参数不同.这里一定要注意,通常我们使用jQuery的$.ajax()规避.
(2) 年份获取函数用getFullYear()替代getYear()
这个可能很多人都知道,在非IE下的getYear获取的当前年份减去1900的数字,这里要么做判断,要么使用getFullYear().
(3) indexOf()函数
在Javascript中使用数组,可能需要会要得到一个元素在数组中的脚标,在标准浏览器中有indexOf()函数,但是在IE中不支持,我们可以自己通过Array.prototype.indexOf = function(obj){...};这样进行拓展.
CSS兼容
提到CSS兼容,这是一个要比Javascript兼容沉重多的话题,当真是无数前端竞折腰.最开始接触CSS的时候我就一个感觉,那就是简单.随便设置设置,然后就可以让页面变换.不过正所谓懂得越多越发现自己无知,这个在CSS的学习上真是够贴切.虽然深入了解,你发现CSS变成了一个大泥潭,各种Bug,兼容什么的搞得你焦头烂额.这个我本人深有体会,不过逃避解决不了问题,尤其对于前端来讲,CSS是你逃不过去的一关.
对于CSS,我个人建议真的就是多去做,做的多了自然对于各个兼容和浏览器Bug有所积累.这里我只想谈谈CSS兼容所要掌握的一些基础,分成两部分,CSS Hack以及CSS Bug.
前者表示不同浏览器针对CSS识别有怎样的标识,后者则是在不同浏览器下那些效果是与正常预计情况不符合的.
一. CSS Hack
(1) CSS属性标识
对于CSS属性,比如color,height,weight这些,如果给这些加入一些特殊的标识,就可以让对应的浏览器才能识别,而其他浏览器会忽略.这样做的效果,就是可以针对同一个样式,针对不同浏览器,我们可以写不同的对应,达到兼容的目的.
CSS属性Hack:
color:red; /* 所有浏览器都识别 */ _color:red; /* 属性名前加下划线"_",这样的属性只有IE6识别 */ *color:red; +color:red; *+color:red; /* "*","+"或者"*+"这三者加在属性名前,那么IE6,IE7都可以识别. */ color:red\9; /* IE6到IE9都识别 */ color:red\0; /* IE8,IE9识别 */ color:red\9\0; color:red \0; /* IE9识别 */
上面是到IE9为止的CSS Hack,IE10和IE11也是有的,不过我看了之后决定还是不写了,因为IE10开始微软对于W3C的标准已经逐渐开始贴近,其中的Hack基本上用不到,不看也罢.
CSS选择器Hack以及注释:
*html #demo {color:red}; /* IE6识别 */ *+html #demo {color:red}; /* IE7识别 */ <!--[if IE 6]>此处内容只有IE6.0可见<![endif]--> <!--[if IE 7]>此处内容只有IE7.0可见<![endif]-->对于Hack这就是常见了的,我没有写的特别完全,因为不是所有的我们的会在日常使用,所以这里就挑出一些常见的,供日常使用.
二. CSS Bug
一般谈到的浏览器兼容,页面兼容其实就是说的CSS Bug.因为浏览器内核渲染机制不同,导致我们编写的CSS与预期的效果有所偏差.CSS Bug有很多,我也无法一一列举,只能找出一些比较常见的.对于解决兼容问题,还是要自己日常积累,可以说做的多了,自然也就知道那些需要特别注意了.
在CSS Bug中数量最多的是IE6上的Bug,比如浮动双倍margin,浮动产生双倍距离等.但是在这里我不打算列出IE6的这些Bug,因为IE6毕竟逐渐走出主流市场,说它是日暮西山也不为过.再好的产品,在IE6上也很难有好的体验,因为投入和回报不成比例,所以这里我只列举出IE8以上的兼容问题,毕竟在中国现在IE8还是很有市场的.
(1) 注意文档类型的声明,也就是<!DOCTYPE>标签一定不能不写,声明好使用什么标准,虽然HTML5只有一个标准,不过就兼容考虑,现在还是要进行HTML4的DOCTYPE声明.
(2) form表单情况下,当img元素包含在label元素内时,单击图片焦点不会转移到相应的表单控件.
<style> li { overflow: hidden; display: inline-block; /* gives layout for IE float clearing */ } li { display: block; } label { float: left; } </style> <form action=""> <ul> <li> <label for="one"><img src="hl_logo.png" alt=""></label> <input type="text" id="one"> </li> </ul> </div> </form>
(3) th不会继承table的text-align样式的内容.
<style> table, tr, td, th { border-collapse: collapse; border: 1px solid #000; } table { text-align: right; } td, th { width: 100px; } </style> <table> <tr> <th>Foo</th> <th>Bar</th> </tr> <tr> <td>Foo</td> <td>Bar</td> </tr> </table>
(4) ul,li中的内容会下沉,li元素中的内容在编号下方.(给a加上float:left即可)
<style> li { border: 1px solid #fff; } a { background: #f00; display: block; overflow: hidden; } </style> <ul> <li><a href="#">one</a></li> <li><a href="#">two</a></li> <li><a href="#">three</a></li> <li><a href="#">four</a></li> </ul>
(5) background设置背景图片,无法显示.(background缩写的情况)
<style> div { width: 500px; height: 115px; background: #fff url(/pics/hl_logo.png)no-repeat; /* note that there is no space after url() part */ } </style> <div></div>
找了一些资料发现IE8下的bug比我想得还是要少很多的,主要是IE6和IE7的比较多.所以这里我就不一一列举了,这个死记硬背没有意义,遇到问题解决问题就好了.通常一个CSS样式的全部初始化会解决很多问题,这样的文件大家可以网上找,很多的.我这里没有列举出太多的CSS兼容示例,因为这个真的很多,而且都写出来你也记不住,挑出比较常见的看一下有个印象,遇到问题知道找什么资料.
兼容说到这里我感觉就差不多了,相比其网上一些文章已经尽量精简了内容.我感觉这方面的知识积累很重要,你做的多了,遇到的多了,自然对各种bug有所了解,也就知道怎么解决.本文列举的仅仅是我个人认为比较常用的一些,不完善之处还请见谅.