目前,最为流行的浏览器共有五个:分别是ie,Edge浏览器(属于微软),火狐,谷歌(chrome)Safari和Opera五大浏览器。

Trident内核:IE ,360,,猎豹,百度;

Gecko内核:火狐----------->这个浏览器内核是开源的浏览器内核,插件非常多,-------------->缺点:打开速度慢(加载flash插件)<-----额外介绍----->。

Presto内核:Opera7及以上版本

Webkit:遨游,苹果 ,symbian;Safari、Chrome

Bink:Chrome(28及往后版本)、Opera(15及往后版本)和Yandex浏览器,大部分国产浏览器最新版本都采用Blink;

对浏览器兼容问题,一般分,HTML,Javascript兼容,CSS兼容。 其中html相关问题比较容易处理,无非是高版本浏览器用了低版本浏览器无法识别的元素,导致其不能解析,所以平时注意一点就是。

一、兼容问题集合

问题一:不同浏览器的标签默认的外补丁和内补丁不同

  • 问题症状:随便写几个标签,不加样式控制的情况下,各自的margin 和padding差异较大。
  • 碰到频率:100%
  • 解决方案:css里 *{margin:0;padding:0;}
  • 备注:这个是最常见的也是最易解决的一个浏览器兼容性问题,几乎所有的css文件开头都会用通配符*来设置各个标签的内外补丁是0。

问题二:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大

  • 问题症状:常见症状是ie6中后面的一块被顶到下一行
  • 碰到频率:90%(稍微复杂点的页面都会碰到,float布局最常见的浏览器兼容问题)
  • 解决方案:在float的标签样式控制中加入 display:inline;将其转化为行内属性
  • 备注:我们最常用的就是div+css布局了,而div就是一个典型的块属性标签,横向布局的时候我们通常都是用div float实现的,横向的间距设置如果用margin实现,这就是一个必然会碰到的兼容性问题。

问题三:设置较小高度标签(一般小于10px),在ie6,ie7,遨游中高度超出自己设置高度

  • 问题症状:ie6、7和遨游里这个标签的高度不受控制,超出自己设置的高度
  • 碰到频率:60%
  • 解决方案:给超出高度的标签设置overflow:hidden;或者设置行高line-height 小于你设置的高度。
  • 备注:这种情况一般出现在我们设置小圆角背景的标签里。出现这个问题的原因是ie8之前的浏览器都会给标签一个最小默认的行高的高度。即使你的标签是空的,这个标签的高度还是会达到默认的行高。

问题四:行内属性标签,设置display:block后采用float布局,又有横行的margin的情况,ie6间距bug(类似第二种)

  • 问题症状:ie6里的间距比超过设置的间距
  • 碰到几率:20%
  • 解决方案:在display:block;后面加入display:inline;display:table;
  • 备注:行内属性标签,为了设置宽高,我们需要设置display:block;(除了input标签比较特殊)。在用float布局并有横向的margin后,在ie6下,他就具有了块属性float后的横向margin的bug。不过因为它本身就是行内属性标签,所以我们再加上display:inline的话,它的高宽就不可设了。这时候我们还需要在display:inline后面加入display:talbe。

问题五:图片默认有间距

  • 问题症状:几个img标签放在一起的时候,有些浏览器会有默认的间距,加上问题一中提到的通配符也不起作用。
  • 碰到几率:20%
  • 解决方案:使用float属性为img布局
  • 备注:因为img标签是行内属性标签,所以只要不超出容器宽度,img标签都会排在一行里,但是部分浏览器的img标签之间会有个间距。去掉这个间距使用float是正道

问题六:标签最低高度设置min-height不兼容

  • 问题症状:因为min-height本身就是一个不兼容的css属性,所以设置min-height时不能很好的被各个浏览器兼容
  • 碰到几率:5%
  • 解决方案:如果我们要设置一个标签的最小高度200px,需要进行的设置为:{min-height:200px; height:auto !important; height:200px; overflow:visible;}
  • 备注:在B/S系统前端开发时,有很多情况下我们有这种需求。当内容小于一个值(如300px)时。容器的高度为300px;当内容高度大于这个值时,容器高度被撑高,而不是出现滚动条。这时候我们就会面临这个兼容性问题。

问题七:透明度的兼容css设置

方法是:每写一小段代码(布局中的一行或者一块)我们都要在不同的浏览器中看是否兼容,当然熟练到一定的程度就没这么麻烦了。建议经常会碰到兼容性问题的新手使用。很多兼容性问题都是因为浏览器对标签的默认属性解析不同造成的,只要我们稍加设置都能轻松地解决这些兼容问题。如果我们熟悉标签的默认属性的话,就能很好的理解为什么会出现兼容问题以及怎么去解决这些兼容问题。

二、技巧

技巧一:css hack

使用hacker 我可以把浏览器分为3类:ie6 ;ie7和遨游;其他(ie8 chrome ff safari opera等)

  • ie6认识的hacker 是下划线_ 和星号 *
  • ie7 遨游认识的hacker是星号 * (包括上面问题6中的 !important也算是hack的一种。不过实用性较小。)

比如这样一个css设置 height:300px;*height:200px;_height:100px; ie6浏览器在读到 height:300px的时候会认为高时300px;继续往下读,他也认识*heihgt, 所以当ie6读到*height:200px的时候会覆盖掉前一条的相冲突设置,认为高度是200px。继续往下读,ie6还认识_height,所以他又会覆盖掉200px高的设置,把高度设置为100px; ie7和遨游也是一样的从高度300px的设置往下读。当它们读到*height200px的时候就停下了,因为它们不认识_height。所以它们会把高度解析为200px; 剩下的浏览器只认识第一个height:300px;所以他们会把高度解析为300px。

因为优先级相同且相冲突的属性设置后一个会覆盖掉前一个,所以书写的次序是很重要的。

/* CSS属性级Hack */ 
color:red; /* 所有浏览器可识别*/

_color:red; /* 仅IE6 识别 */

*color:red; /* IE6、IE7 识别 */ +color:red; /* IE6、IE7 识别 */ *+color:red; /* IE6、IE7 识别 */ [color:red; /* IE6、IE7 识别 */ color:red\9; /* IE6、IE7、IE8、IE9 识别 */ color:red\0; /* IE8、IE9 识别*/ color:red\9\0; /* 仅IE9识别 */ color:red \0; /* 仅IE9识别 */ color:red!important; /* IE6 不识别!important 有危险*/ /* CSS选择符级Hack */ *html #demo { color:red;} /* 仅IE6 识别 */ *+html #demo { color:red;} /* 仅IE7 识别 */ body:nth-of-type(1) #demo { color:red;} /* IE9+、FF3.5+、Chrome、Safari、Opera 可以识别 */ head:first-child+body #demo { color:red; } /* IE7+、FF、Chrome、Safari、Opera 可以识别 */ :root #demo { color:red\9; } : /* 仅IE9识别 */

越少的浮动,就会越少的代码,会有更灵活的页面,会有扩展性更强的页面。这不多说,归结为到一定水平了,浮动会用的较少。另外,您也会避免使用浮动+margin的用法。所以,越后来越不易遇到这种bug。

技巧二:padding,marign,height,width

注意是技巧,不是方法: 写好标准头 http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”> http://www.w3.org/1999/xhtml”> 尽量用padding,慎用margin,height尽量补上100%,父级height有定值子级height不用100%,子级全为浮动时底部补个空clear:both的div宽尽量用margin,慎用padding,width算准实际要的减去padding

技巧三:显示类(display:block,inline)
display:block,inline两个元素

display:block; //可以为内嵌元素模拟为块元素

display:inline; //实现同一行排列的的效果 display:table; //for FF,模拟table的效果

display:block块元素,元素的特点是: 总是在新行上开始;高度,行高以及顶和底边距都可控制;宽度缺省是它的容器的100%,除非设定一个宽度

display:inline就是将元素显示为行内元素,元素的特点是:和其他元素都在一行上;高,行高及顶和底边距不可改变;宽度就是它的文字或图片的宽度,不可改变。span,a,label,input,img,strong和em是 inline 元素的例子

技巧四:怎样使一个div层居中于浏览器中?

1)



<style type="text/css">

<!-- div {

position:absolute;

top:50%;

left:50%;

margin:-100px 0 0 -100px;

width:200px;

height:200px;

border:1px solid red; } -->

</style>



2)div里的内容,IE默认为居中,而FF默认为左对齐,可以尝试增加代码margin: 0 auto;

技巧五:float的div闭合;清除浮动;自适应高度

① 例如:<div id="floatA"><div id="floatB"><div id="NOTfloatC">

  • 这里的NOTfloatC并不希望继续平移,而是希望往下排。(其中floatA、floatB的属性已经设置为float:left;)
  • 这段代码在IE中毫无问题,问题出在FF。原因是NOTfloatC并非float标签,必须将float标签闭合。在<divclass="floatB"><div class="NOTfloatC">之间加上<div class="clear">这个div一定要注意位置,而且必须与两个具有float属性的div同级,之间不能存在嵌套关系,否则会产生异常。并且将clear这种样式定义为为如下即可:.clear{clear:both;}

②作为外部 wrapper 的 div 不要定死高度,为了让高度能自适应,要在wrapper里面加上overflow:hidden; 当包含float的box的时候,高度自适应在IE下无效,这时候应该触发IE的layout私有属性(万恶的IE啊!)用zoom:1;可以做到,这样就达到了兼容。 
例如某一个wrapper如下定义:

.colwrapper{overflow:hidden; zoom:1; margin:5px auto;}

③对于排版,我们用得最多的css描述可能就是float:left.有的时候我们需要在n栏的float div后面做一个统一的背景,譬如:

<div id=”page”>

<div id=”left”></div> <div id=”center”></div> <div id=”right”></div> </div>

比如我们要将page的背景设置成蓝色,以达到所有三栏的背景颜色是蓝色的目的,但是我们会发现随着left centerright的向下拉长,而page居然保存高度不变,问题来了,原因在于page不是float属性,而我们的page由于要居中,不能设置成float,所以我们应该这样解决:

<div id=”page”>

<div id=”bg” style=”float:left;width:100%”> <div id=”left”></div> <div id=”center”></div> <div id=”right”></div> </div> </div>

再嵌入一个float left而宽度是100%的DIV解决之。

④万能float 闭合(非常重要!)

关于 clear float 的原理可参见 [How To ClearFloats Without Structural Markup],将以下代码加入Global CSS 中,给需要闭合的div加上class=”clearfix”即可,屡试不爽。

/* Clear Fix */ 
.clearfix:after { content:"."; display:block; height:0; clear:both;visibility:hidden; } .clearfix { display:inline-block; } /* Hide from IE Mac */ .clearfix {display:block;} /* End hide from IE Mac */ /* end of clearfix */

或者这样设置:.hackbox{display:table; //将对象作为块元素级的表格显示}

技巧六:div嵌套时 y轴上 padding和 marign的问题

  • FF里 y 轴上 子div 到 父div 的距离为 父padding + 子marign
  • IE里 y 轴上 子div 到 父div 的距离为 父padding 和 子marign 里大的一个
  • FF里 y 轴上 父padding=0 且 border=0 时,子div 到 父div 的距离为0,子marign 作用到 父div 外面

一、360显示不正确

Web页面在360等浏览器上,显示不正确。 但是在Firefox、chrome和IE8+以上的浏览器上,都是显示正常的。

问题的分析

  1.  检查了一些Javascript框架,标准的jquery类库1.x系列,确认其工作正常,问题不是在于Javascript方面。

  2.  排查掉HTML标签内容的显示 问题。

  3.  怀疑是CSS在不同浏览器下的兼容性问题,见过排查,没有发现问题。

  4.  排查360浏览器,发现其在当前页面的显示中,默认使用了IE7的渲染引擎。同时,在IE7的环境下,重现了类似情况。

  5.  本质上,这个显示问题是页面在IE7下面的兼容性显示问题。

通过实验,发现只有在IE7内核下面才存在兼容性显示问题

发现问题的产生是浏览器“兼容模式”惹的祸

 

关于360浏览器或搜狗浏览器的分析:

  对于此类浏览器,有时候号称双核或者N核的高速浏览器,其本质上就是本地IE浏览器的壳子,外加Chrome抑或Firefox的内核,大部分情况下都是WebKit系列内核。

那么,此类浏览器依据什么信息,来判断页面的渲染模式呢?答案就是可以指令运行当前页面的浏览器使用何种渲染引擎的声明。

<meta http-equiv="X-UA-Compatible" content="IE=8">

这里,就是指令浏览器至少要使用IE8以上的渲染引擎来,渲染页面,从而规避掉IE7下的问题。

于是在header中加入以下代码,我认为真正起作用的是第二行代码,但为了保险起见,两行我都选用



<meta name="renderer" content="webkit"> <meta http-equiv="X-UA-Compatible" content="IE=8">



于是页面即使在兼容模式下也恢复正常显示。但还有一个问题,显然这样在使用原生的IE浏览器浏览时也会选用ie8内核,我还需要修改一下。

于是,将代码中的8改为11,<meta http-equiv="X-UA-Compatible" content="IE=11">,问题解决。 

关于Doctype. 

<!DOCTYPE> 声明必须是 HTML 文档的第一行,位于 <html> 标签之前。

<!DOCTYPE> 声明不是 HTML 标签;它是指示 web 浏览器关于页面使用哪个 HTML 版本进行编写的指令。

在 HTML 4.01 中,<!DOCTYPE> 声明引用 DTD,因为 HTML 4.01 基于 SGML。DTD 规定了标记语言的规则,这样浏览器才能正确地呈现内容。

分析:  doctype所要解决的就是使用何种HTML的语法解析器和渲染器。比如特定HTML标签的使用,则依赖于HTML Doctype的使用。

二、innerText和textContent

nnerText 谷歌,火狐和IE8都支持
低版本 的火狐不支持innerText
textContent在IE8中的结果是undefined;
textContent在谷歌和火狐中支持;

这些内容是必须知道的,也是以后解决兼容性问题的引子或者思路,同时也是基础。

在解决浏览器兼容性的问题上面,首先,可以通过获取浏览器的版本来判断这个浏览器是不是支持这个属性,但是这种办法非常的麻烦。
具体做法是:我要在一系列的信息中找到这个浏览器版本里面的具体是什么样的,然后用正则表达式去匹配,然后确定这个浏览器里面具体用的什么东西。这就是整个的内容,所以,相当的麻烦。
当然,获取浏览器版本的代码很简单,就一句话,一行代码,但是仅仅是为了判断这个浏览器是不是支持这个属性 ,是不是放在这里好像有点儿大材小用了。因此,就直接判断这个浏览器里面是不是支持这个属性就可以了。

为了解决这个不兼容的问题,我们可以编辑以下代码来解决上述问题:



1 //任意元素都可以设置成文本内容----------因此把“任意”元素当成对象(element)传递到函数中
 2 
 3     //element---->任意元素 
 4     //text--->任意文本内容 
 5     function setInnerText(element,text) { 
 6     if(typeof (element.textContent)=='undefined'){//是IE8浏览器 
 7     element.innerText=text; 
 8        }else{ 
 9     //浏览器支持textContent这个属性 
10      element.textContent=text; 
11         } 
12     } 
13 
14 
15       //获取任意元素中的文本内容 
16     function getInnerText(element) { 
17     if(typeof (element.textContent)=="undefined"){ 
18     //如果浏览器不支持textContext这个属性则返回innerText的值 
19     return element.innerText; 
20         }else{ 
21     //如果浏览器支持textContext属性,则直接返回该属性的值 
22     return element.textContent; 
23         } 
24     }



上述代码就可以解决innnerText和textContent在各个浏览器之间不兼容的问题(上述代码目前只在谷歌,火狐,IE8版本上面测试,以后还会在其他的浏览器的不同版本上面测试,测试结果还会不断的更新,尽请期待)。

上面介绍的内容只阐述部分属性在各个浏览器上面的差异,当然,还有其他的兼容问题存在,他们分别是:

(1)获取某个元素中的第一个子元素 

(2)获取某个元素中的最后一个子元素 

(3)获取某个元素的前一个兄弟元素 

(4)获取某个元素的后一个兄弟元素 

下面,我分别给出了相应的兼容性问题解决办法代码:



1 //获取某个元素中的第一个子元素 
 2     function getFirstElement(element) { 
 3     if(element.firstElementChild){ 
 4     //如果浏览器支持这个属性就直接返回第一个子元素 
 5     return element.firstElementChild; 
 6     }else{ 
 7     //如果浏览器不支持这个firstElementChild属性,先获取传入进来的父级元素中的第一个子节点 
 8     var node=element.firstChild;//先获取这个节点 
 9     while (node&&node.nodeType!=1){//判断节点存在并且不是标签 
10     node=node.nextSibling;//继续找当前节点的下一个节点 
11     } 
12     return node; 
13     } 
14     } 
20     //下面这连个属性在各个不同的浏览器中显示的方式有所不同
21     //my$("uu").firstChild 
22     //my$("uu").firstElementChild 
23     
24     //获取某个元素中的最后一个子元素 
25     function getLastElement(element) { 
26     if(element.lastElementChild){ 
27     return element.lastElementChild; 
28     }else{ 
29     //获取当前元素的最后一个子节点 
30     var node=element.lastChild; 
31     while (node&&node.nodeType!=1){ 
32     node=node.previousSibling; 
33     } 
34     return node; 
35     } 
36     } 

44     
45     //获取某个元素的前一个兄弟元素 
46     function getPreviousElement(element) { 
47     if(element.previousElementSibling){ 
48     return element.previousElementSibling 
49     }else{ 
50     var node=element.previousSibling; 
51     while (node&&node.nodeType!=1){ 
52     node=node.previousSibling; 
53     } 
54     return node; 
55     } 
56     } 
57     
58     
59     
60     //获取某个元素的后一个兄弟元素 
61     function getNextElement(element) { 
62     if(element.nextElementSibling){ 
63     return element.nextElementSibling 
64     }else{ 
65     var node=element.nextSibling; 
66     while (node&&node.nodeType!=1){ 
67     node=node.nextSibling; 
68     } 
69     return node; 
70     } 
71     }