把这些地方都注意了,你的网站就不会有那么多的兼容问题了
根据我的实践经验。如果你在写HTML/CSS时候是按照W3C推荐的方式写的,那么基本的浏览器兼容问题都是可以避免的。
这里主要考虑是的ie8-,个人目测Ie9+的渲染效果已经跟的上主流了。
测试ie兼容最好要在win7+上测试,因为winXP最高支持IE8。
这里贴出百度统计的浏览器市场份额:
PC端:
再给一张国外的
测试网址http://gs.statcounter.com/
目测谷歌是主流啊,变化平稳。排在第二的是IE8,Ie6的地位还是有的,不过占有率不高了,如果不是做学校政府机关方面的基本可以忽略不计了。
个人建议你的项目考虑是浏览器:谷歌,ie8+,Firefox,Safari,opera,360浏览器,搜狗。这些浏览器最好都用真实设备实测。
OK,现在我们就来写点小代码避免浏览器不兼容的问题吧。
DOCTYPE
首先要确保你的HTML页面开始有DOCTYPE声明。DOCTYPE告知浏览器使用什么样的HTML或XHTML规范来解析HTML文档。DOCTYPE还会对浏览器的渲染模式产生影响,不同的渲染模式会影响到浏览器对CSS甚至JS的解析。尤其是IE系列的浏览器,由DOCTYPE所决定的HTML页面渲染可以差很多,可以把你的页面弄个面目全非。
看下面的声明,这是我以前常用的DOCTYPE声明
<span style="font-family:SimSun;"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></span>
- DOCTYPE html :页面的文档类型是HTML
- PUBLIC:是公共的,可以个人家查看的,打开页面右击查看源代码。
- "-//W3C//DTD XHTML 1.0 Transitional//EN":是w3c这个组织定义的 XHTML 1.0 过渡型 语言是英文
- http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd:可以到这个网址下面找到相关的规范
参考:
http://w3help.org/zh-cn/kb/001
http://w3help.org/zh-cn/casestudies/002
http://www.w3cschool.cn/tag_doctype.html
上面推荐使用(项目中都用这声明了)
<span style="font-family:SimSun;"><!DOCTYPE html></span>
在我以前的项目里。后端的同志们老是觉得这个声明没啥用,总自作主张的把它删掉,或者乱用这个声明,因为即使你删除或者乱用都不会报错的,但是偏偏在某个浏览器下就出现这样那样的问题,找你过去看了半天,原来他把DOCTYPE声明给删除了,我真心想说靠。这是一个小细节,希望童鞋们都注意了。
解决方案:
使用头部开始
<!DOCTYPE html>
使用meta标签调节浏览器的渲染方式
IE8发布的时候,相对于IE6/7已经做出了相当大的改进,向w3c漫进很大一步。IE8发布的时候,当时很多的网站都是基于Ie6/7来做处理的,如果瞬间改为ie8渲染,有点不科学。所以ie8就加入了“兼容模式”功能,这样就可以再Ie8浏览器中
使用Ie6/7的内核渲染页面。但是对于现在的我们来说,我们是不需要这样的。所以我们可以使用meta标签来强制的让Ie8使用最新的内核渲染页面。
<span style="font-family:SimSun;"> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"></span>
- IE=edge:使用最新的IE内核。
- chrome=1:如果安装了谷歌就让IE浏览器的外观不变,内核渲染用谷歌。当然了官方的说法不是安装了谷歌的浏览器。
国内的很多浏览器都是双核浏览器,比如306浏览器,搜狗,它们是怎么决定用哪个内核来渲染页面的呢?
这里引用了360浏览器帮助的一段文字来回答:
“由于众所周知的情况,国内的主流浏览器都是双核浏览器:基于Webkit内核用于常用网站的高速浏览。基于IE的内核用于兼容网银、旧版网站。以360的几款浏览器为例,我们优先通过Webkit内核渲染主流的网站,只有小量的网站通过IE内核渲染,以保证页面兼容。在过去很长一段时间里,我们主要的控制手段是一个几百k大小网址库,一个通过长期人工运营收集的网址库。
尽管我们努力通过用户反馈、代码标签智能判断技术提高浏览器的自动切核准确率。但是在很多情况下,我们仍然无法达到百份百正确。因此,我们新增加了一个控制手段:内核控制Meta标签。只要你在自己的网站里增加一个Meta标签,告诉360浏览器这个网址应该用哪个内核渲染,哪么360浏览器就会在读取到这个标签后,立即切换对应的内核。并将这个行为应用于这个二级域名下所有网址。
目前该功能已经在所有的360安全浏览器实现。我们也建议其它浏览器厂商一起支持这个实现。让这个控制标签成为行业标准。”
360浏览器建议我们采用webkit
<span style="font-family:SimSun;"><meta name="renderer" content="webkit"></span>
解决方案:
在任何页面的头部加上
<!-- 指定以最新的IE版本模式来显示网页 --> <meta http-equiv="X-UA-Compatible" content="IE=edge,<span style="font-family: SimSun;">chrome=1</span> " /> <!-- 360浏览器相关设置:http://se.360.cn/v6/help/meta.html --> <!-- 针对360浏览器的内核调用,强制调用极速模式 --> <meta name="renderer" content="webkit" /> <!-- 针对360浏览器强制调用IE标准模式 --> <!--[if lt IE 10]> <meta name="renderer" content="ie-stand" /> <![endif]--> <!--[if !IE]> <meta name="renderer" content="ie-stand" /> <!<![endif]-->
在火狐中注释解析错误
标准做法
<span style="font-family:SimSun;">// 单行注释 <!-- this is a comment --> // 多行注释 <!-- and so is this one, which occupies more than one line --></span>
注意的是:
- 注释元素的开始标签"<!">和"--"之间不能有空白符存在,但是在其他浏览器中,就算有空白符也可以正确的识别。
<span style="font-family:SimSun;">// 此处的注释,在各浏览器下,都能被作为注释标签正常识别 <! -- this is a comment --> </span>
- 注释元素的关闭标签”--“和">"之间允许有空白符。
- 应该避免在注释内容中出现两个或以上的”-“字符,否则可能出现错误。这个问题将导致页面中的注释部分在火狐的标准模式下被当做文本内容解析出来。
<span style="font-family:SimSun;"><!-- 这里是---注释内容 --></span>
解决方案
按标准推荐的方法写注释标签,如:
<!-- //此处 "<!" 和 "--" 之间尽量不要有空格。
这里是注释内容,应避免在注释内容中出现两个或以上的“-”字符。
--> //此处 "--" 和 ">" 之间避免有空格。
不同浏览器对字符编码别名支持的宽泛程度存在差异
根据规范,服务器应该提供给用户端文档的字符编码信息,最直接的方式为通过http协议”Content-Type“头字段的”charset“将文档字符编码告诉用户端。
如:http头声明了字符编码为UTF-8。
<span style="font-family:SimSun;"><pre name="code" class="javascript">Content-Type<span style="font-family: Arial, Helvetica, sans-serif;">="text/html;charset=UTF-8"</span></span>处于某种情况无法访问服务器时,html文档可以包含有关文档的字符编码的明确信息,meta元素可以用来为用户端提供这些信息,
<span style="font-family:SimSun;"><meta http-equiv="Content-Type" content="text/html;charset=UTF-8"></span>
当http协议和meta元素均没有提供有关一个文档的字符编码信息时,html还为一些元素提供了charset属性,
优先级:
- http”Content-Type“字段中的”charset“参数
- meta中的http-equiv="Content-Type"对应的”charset"值
- 元素的“charset”属性
各浏览器中运行效果如下:
IE6 IE7 IE8 Firefox | Chrome Safari | Opera |
---|---|---|
字符编码 --- GB2312 | ×Ö·û±àÂë --- ISO-8859-1 | 字符编码 --- GBK |
解决方案:
首先,对于动态页面必须确保 HTTP "Content-Type" 头字段的 "charset" 参数与页面自身编码相符,且务必在页面的 META 元素中也声明相符的字符编码信息。对于静态页面,必须保证页面中
META 元素声明中 "http-equiv" 为 "Content-Type" 对应的值中的 "charset" 的值与页面自身编码相符。
其次,在设置字符编码别名时,最好使用最通用的、各浏览器均可识别的编码别名。
DTD之前的非空字符在某些情况下会使该DTD失效
规范中提到,DTD的前面或后面允许出现空白符(空格符,换行符,制表符和注释)。但是如果在DTD之前加入注释或其他内容,在某些浏览中改DTD可能会无效。
- IE6 DTD 前的任何非空白符都将使浏览器忽略 DTD,包括注释和 XML 声明。
- IE7 IE8 DTD 前的任何非空白符都将使浏览器忽略 DTD,包括注释,但不包括 XML 声明。
- Firefox DTD 前的任何包含“<”的字符都将使浏览器忽略 DTD,但不包括 XML 声明。
- Chrome Safari Opera DTD 前的任何非空白符都将使浏览器忽略 DTD,但不包括 XML 声明。
一个 HTML 文档的 DTD 前边如果出现其他字符,在各浏览器中的处理情况是不一致的。
具体差异请参考下表:
如果 DTD 之前出现 | 浏览器是否能识别该 DTD | ||||||
---|---|---|---|---|---|---|---|
IE6 | IE7 | IE8 | Firefox | Chrome | Safari | Opera | |
空格符 换行符 制表符 | 可以识别 | 可以识别 | 可以识别 | 可以识别 | 可以识别 | 可以识别 | 可以识别 |
注释1 | 不能识别 | 不能识别 | 不能识别 | 可以识别 | 可以识别 | 可以识别 | 可以识别 |
XML 声明2 | 不能识别 | 可以识别 | 可以识别 | 可以识别 | 可以识别 | 可以识别 | 可以识别 |
其他不包含“<”的字符3 | 不能识别 | 不能识别 | 不能识别 | 可以识别 | 不能识别 | 不能识别 | 不能识别 |
其他包含“<”的字符4 | 不能识别 | 不能识别 | 不能识别 | 不能识别 | 不能识别 | 不能识别 | 不能识别 |
【注】
1. 即HTML注释,如 <!-- comment -->。
2. 类似 <?xml version="1.0" encoding="utf-8"?> 的 XML 声明。
3. 即不是空格符、换行符、制表符,也不是注释、XML 声明的任何其他字符串,但不能包含“<”字符。
4. 即不是空格符、换行符、制表符,也不是注释、XML 声明的任何其他字符串,其中包含“<”字符。
通过以上对比可以看出,要保证 DTD 在所有浏览器中都能正常识别,DTD 之前只能出现空格符、换行符和制表符。
解决方案
声明 DTD 时,确保 DTD 之前没有其他字符,即便有,也只能是空格符、换行符和制表符。
如将 DTD 放在 HTML 文档的第一行。
Chrome 和 Safari 中标签紧密相邻的行内元素在折行显示时存在错误
这个问题是 WebKit 引擎在处理紧密相连的内联元素时存在自动换行计算上的 Bug 。
针对此问题,我们使用以下测试样例来说明,分析以下代码:
<span style="font-family:SimSun;"><body> <a>[a]</a><span>[span]</span><strong>[strong]</strong><i>[i]</i><b>[b]</b><big>[big]</big><small>[small]</small><em>[em]</em><dfn>[dfn]</dfn><code>[code]</code><samp>[samp]</samp><kbd>[kbd]</kbd><var>[var]</var><cite>[cite]</cite><abbr>[abbr]</abbr><acronym>[acronym]</acronym><sub>[sub]</sub><sup>[sup]</sup><bdo>[bdo]</bdo> </body></span>
减小浏览器窗口尺寸后,在各浏览器中表现如下:
Chrome Safari | IE6 IE7 IE8 Firefox Opera |
---|---|
通过上图比较可以发现,在非 WebKit 引擎的浏览器内,不管元素排列如何紧密,都可以随着布局大小自动换行显示; 而在 WebKit 引擎的浏览器中所有紧密相连的内联元素都在同一行显示,并且与文档模式无关。
解决方案
避免出现紧密连接的内联元素标签,可以在每个标记之间加入空格或者换行符来避免这个问题。
Chrome 和 Safari 中 BR 元素前的空白符不会被忽略
W3C 规定 "ASCII 空格" 、 "ASCII 制表符" 、 "ASCII 换行符" 等属于空白符(white space),对于多个连续的空白符,浏览器将对他们进行合并。
BR 元素会在当前行强制插入一个换行符,这个换行符也是空白符的一种。
Chrome 和 Safari 中 BR 元素前的空白符不会被忽略,多余的空白符将被压缩为一个空白符并渲染到 BR 元素之前的行中。这个现象可能造成在 Chrome 和 Safari 中出现多余空白符占有位置,从而影响到容器的宽度或者行内元素的对齐效果。
<div style="zoom:1; overflow:hidden; margin-top:10px;">
<p style="text-align:right;">
<span style="background:#ddd;">A</span> <br /><span style="background:#eee;">B</span>
</p>
<p style="text-align:center;">
<span style="background:#ddd;">A</span> <br /><span style="background:#eee;">B</span>
</p>
<p style="text-align:left;">
<span style="background:#ddd;">A</span> <br /><span style="background:#eee;">B</span>
</p>
</div>
Chrome Safari 没有忽略 BR 元素之前的空白符。而 其他浏览器 则将其忽略。
仅当容器的宽度不够容纳子元素时,Chrome Safari 才会忽略 BR 元素之前的空白符。
解决方案
删除 BR 元素之前多余的空白符。
各浏览器下使用object元素和embed元素嵌入flash存在差异
object元素定义了一个嵌入的对象,通常情况下,IE系列通过ActiveX插件使用object元素引入flash,而其他浏览器则通过相应的插件使用embed元素。这就造成了各浏览器中插入flash的方式的差异。
若仅仅使用 OBJECT 元素设置了 classid 属性引入 Flash,则可能造成在某些浏览器中 Flash 无法被引入。而若嵌套的 OBJECT 和 EMBED 元素参数不统一,也可能造成引入的 Flash 在各浏览器中出现差异。
通常我们会使用如结构代码引入flash:
<object width="200" height="200" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#4,0,0,0">
<param name="src" value="clock.swf" />
<param name="quality" value="high" />
<embed src="clock.swf" type="application/x-shockwave-flash" width="200" height="200" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
</object>
将embed元素嵌套在object元素中,ie就会优先使用object元素而忽略embed元素,在其他浏览中则优先使用embed元素而忽略object元素。这样做虽然可以保证在所有浏览器中均能正确加载flash,但若object元素和embed元素的参数设定不统一,则导致flash在各个浏览器中显示效果不一致,甚至无法正常加载。
官方给出如下html中引用flash的情况。请参考 Adobe 官方知识库文档:OBJECT and EMBED syntax | Flash 与 Flash OBJECT and EMBED tag attributes中的内容。
<span style="font-family:SimSun;"><object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="550" height="400" id="movie_name" align="middle"> <param name="movie" value="movie_name.swf"/> <!--[if !IE]>--> <object type="application/x-shockwave-flash" data="movie_name.swf" width="550" height="400"> <param name="movie" value="movie_name.swf"/> <!--<![endif]--> <a href="http://www.adobe.com/go/getflash"> <img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash player"/> </a> <!--[if !IE]>--> </object> <!--<![endif]--> </object></span>
使用 EMBED 元素:flash_embed.html
<div style="border:5px solid black; padding:5px; float:left;">
<embed src="clock.swf" type="application/x-shockwave-flash" width="200" height="200" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer"></embed>
</div>
直接使用 EMBED 元素,所有浏览器均支持。
解决方案
- 若不考虑 W3C 校验,可统一使用 EMBED 元素嵌入 Flash,这样可以避免因参数不统一导致的兼容性问题。
- 若需要考虑 W3C 校验(
Markup Validation Service),则可使用第三种单独使用 OBJECT 与 PARAM 元素的方式。
- 若必须使用 OBJECT 嵌套 EMBED 元素这种混合方式,则要保证 Flash 文件 URL、为 Flash 传递的参数、宽度、高度、wmode 等参数保持统一。
- 可以使用开源的 SWFObject 引入 Flash。(请参见:
)
各浏览器对align="middle"的理解有差异
在规范中该属性可以看到不同的align属性,作用在不同的元素上,align属性的意义也不同。
- object,img,applet:取值为“bottom,middle,top,left,right”这个属性指定了它们与其上下文本的位置关系。
- table:取值为“center,left,right”,这个属性指定了table元素在文档中的位置。
- hr:取值为“center,left,right”,这个属性指定了水平线在其上下文之间的水平对齐方式,默认为”center“。
- div,H1~H6,p:取值“center,left,right,justify”,指定了它们在其上下文环境内的水平对齐方式,默认为”left".
- col,colgroup,tbody,td,tfoot,th,thead,tr:“center,left,right,justify,char”,指定了单元格中数据及文本的对齐方式,对于td默认为“left”,对于th默认为“center”。
问题:
firefox,chrome,safari会将div,H1~H6 P元素的align=“middle”解析为align=“center”。从而使这些元素能够居中对齐。
火狐混杂模式会将table元素align=“middle”解析为align=”center“,使table居中对齐。
IE6/7 ,chrome safari opera及ie8,firefox的混杂模式下,会将td,th元素的align=”middle“理解为align=”center“。
影响:
不正确使用align属性的”middle“属性值会在各浏览器中对应用元素的对齐方式产生差异,从而造成布局上的兼容性问题。
解决方案:
align="middle" 仅在 IMG、OBJECT、APPLET 元素上的 align 属性中是合法值,对于其他元素的 align 属性均为非法。各浏览器在上述三个元素之外的元素上遇到 align="middle" 均按照自己的理解方式解释。同时除单元格元素的 align 属性之外,其他的 align 属性均被 W3C 官方废弃(Deprecated.),所以应避免使用此属性。
align="middle" 仅在 IMG、OBJECT、APPLET 元素上的 align 属性中是合法值,对于其他元素的 align 属性均为非法。各浏览器在上述三个元素之外的元素上遇到 align="middle" 均按照自己的理解方式解释。同时除单元格元素的 align 属性之外,其他的 align 属性均被 W3C 官方废弃(Deprecated.),所以应避免使用此属性。
不能以size属性精确控制input文本框或密码框的宽度
问题:
字体的样式会影响根据input元素的”size“属性计算的文本框宽度,其中包括”font-family","font-size","font-syle","letter-spacing".若仅仅为input元素设置“size”属性,却没有显式地设定宽度,则在不同的浏览器中input元素会出现不同的宽度。
解决方案:
不要试图通过设置 "size" 属性使 INPUT[type=text/password] 元素在所有浏览器中的宽度一致,这是不可能的。在需要对这类元素做精确的控制时,应使用 CSS 的 'width' 和 'height' 特性。
另外不同浏览器的默认字体的区别会导致文本框内文字表现的差异,最好为 INPUT 元素显式设置字体样式覆盖其默认值,以保证文本框在所有浏览器中有相同的呈现效果。
各浏览器中密码框掩码的外观不完全一致
W3C没有规定用户端用于隐藏用户实际输入文本的“掩码”的文字编码和相关字体特性。
问题:
密码框中的掩码用来覆盖密码明文,它没有相应规范指定统一显示样式,因此导致不同系统与不同浏览器中密码框“input[type="password"]的掩码字符均有很大的差异。可幸的是,这种差异只会在视觉上产生不同,而不会造成布局上的差异。
检查浏览器对于 input[type=password] 标记的相关默认字体样式设置:
汇总后得到如下字体样式的差异表:
IE6 IE8 IE8(EmulateIE7) | IE7 Firefox | Safari | Chrome | Opera | |
---|---|---|---|---|---|
font-family | Tahoma | SimSun | SimSun | Arial | 宋体 |
font-weight | 400 | 400 | normal | normal | 400 |
font-size | 13px | 13px | 13px | 13px | 13px |
可见各浏览器中 'font-weight' 及 'font-size' 定义没有差异。
查看掩码字符,过滤的众多可疑的圆点字符后,总结出下表:
IE7 Firefox | IE6 IE8 Chrome Safari | Opera | |
---|---|---|---|
TEXT-UNICODE | 0x25cf | 0x2022 | 0x002a |
将上下两表结合,重现各浏览中掩码字符的默认样式如下:
IE6 IE8 IE8(EmulateIE7) | IE7 Firefox | Safari | Chrome | Opera | |
---|---|---|---|---|---|
font-family | Tahoma | SimSun | SimSun | Arial | 宋体 |
font-weight | 400 | 400 | normal | normal | 400 |
font-size | 13px | 13px | 13px | 13px | 13px |
TEXT-UNICODE | 0x2022 | 0x25cf | 0x2022 | 0x2022 | 0x002a |
显示效果 | ●●● | ●●● | ••• | ••• | *** |
解决方案:
由于掩码字符无法被修改,因此仅通过 CSS 统一密码输入框的掩码样式是不可能的。且这种差异可以忽略不计。
这里给出两种解决思路:
- 通过 CSS hack 方式对不同的浏览器设置不同的字体和字号,除去 Opera 外,可以减小掩码样式的差异。
- 或者使用 JavaScript 对普通的文本输入框做输入监听编程,用自定义掩码字符填充输入框来制做自定义密码输入框效果。
firefox opera中object元素的默认尺寸为不可视
规范中对object元素的渲染规则:
- 用户端先必须尝试渲染object,而不应该渲染其内容,但在其内部包含param一级子元素时必须对它们进行检查。
- 若用户端出于某种原因无法渲染object,则必须尝试渲染其内容。
问题:
firefox opera中object元素的默认尺寸为不可视,而IE中,object默认尺寸为16*16PX,在chrome和safari中默认尺寸为300*150px。
也就是说,如果没有为object元素设置明确的宽度和高度,则可能在各浏览器中由于其内在尺寸不同导致最终布局上的差异。
解决方案:
OBJECT 元素为替换元素,应为 OBJECT 元素设置一个明确的宽度和高度。
Firefox 中 TEXTAREA 元素根据 'rows' 设置值生成的实际行数为设置值 + 1
解决方案:
当我们仅仅为 TEXTAREA 元素设置 "rows" 属性以控制其高度时,在 Firefox 中无法得到我们预期的效果。且其他浏览器对 "rows" 属性设置的元素高度也不尽相同,这一点 W3C 没有明确规范 "rows" 属性计算高度时的具体算法。
如果要精确控制 TEXTAREA 元素的尺寸(高度)时,请避免使用 "rows" 属性改用 CSS 相关设定,以保证所有浏览器拥有统一的视觉样式。