原文地址:http://www.csdn.net/article/2012-10-22/2811049-Understanding-the-browser-compatibility-
摘要:关于各种浏览器模式,网上已经有许多文档和资料了,但是很少有能够完全将几个概念阐述清楚的。大部分的资料稍显过时,有些内容可能已经不再适用了。本文中笔者将尽可能将几个概念阐述清楚,并去掉一些过时的内容,仅保留必要的干货。

想必你一定知道浏览器有个标准(Standards)模式和一个怪异(Quirks)模式,或许你还听说过有个“准标准(Almost Standards)”模式。而当你打开Internet Explorer的时候,又看到了什么浏览器模式、文档模式,还有什么兼容性视图等等...

这些都是什么?啥是浏览器模式,啥是文档模式?标准模式和准标准的模式有什么区别?IE9兼容性视图和真正的IE9有什么区别?什么情况下会触发这些模式,又该怎样才能检测到浏览器当前处于哪种模式中呢?本文将详细为你解答这些疑问。

三种模式

首先我们要知道,为什么会有这么多模式。其实这是个历史遗留问题,在浏览器大战时期,网景浏览器(Netscape Navigator)和微软的IE浏览器(Microsoft Internet Explorer)对网页分别有不同的实现方式,那个时候的网页要针对这两种浏览器分别开发不同的版本。而到了W3C制定标准之后,这些浏览器就不能继续使用这种页面了,因而会导致大部分现有站点都不能使用。基于这个原因,浏览器才引入两种模式来处理一些遗留的站点。

现在的浏览器排版引擎支持三种模式:怪异(Quirks)模式、准标准(Almost Standards)和标准(Standards)模式。在怪异模式中,排版引擎会模拟 网景4和Windows中的IE5的行为;在完全标准的模式中,会尽量执行HTML和CSS规范所指定的行为;而在准标准模式中,则只包含很少的一部分怪异模式中的行为。

那么所谓标准模式,就一定都“标准”吗?答案当然是否定的,因为各个浏览器厂商实现标准的阶段不同,所以各个浏览器的“标准模式”之间也会有很大的不同。

Firefox、Safari、Chrome、Opera (自 7.5 以后)、 IE8 和 IE9 都有一个准标准模式。那么既然标准模式都不那么标准,准标准的模式肯定就更不标准了。最初的准标准模式只会影响表格中的图像,而后来各个浏览器又或多或少地进行了修改。那么什么情况下会触发准标准模式呢?是的,正如你所想到的,某些DOCTYPE会触发准标准模式,例如:

 
  1. "-//W3C//DTD XHTML 1.0 Transitional//EN"
  2. "-//W3C//DTD XHTML 1.0 Frameset//EN"
  3. "-//W3C//DTD HTML 4.01 Transitional//EN"
  4. "-//W3C//DTD HTML 4.01 Frameset//EN"
  5. "http://www.ibm.com/data/dtd/v11/ibmxhtml1-transitional.dtd"

一个完整的 DOCTYPE 例子如下:

 
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  2. "http://www.w3.org/TR/html4/loose.dtd">

如果在Firefox中插入这种DOCTYPE,并在页面中插入一个空的span标签,那么在Firebug中查看元素的布局就会发现不同:

准标准模式中元素的line-height被忽略了,元素既没有宽度也没有高度:

标准模式中元素仍然保留了line-height,拥有18px的高度:

在Firefox浏览器中,使用鼠标右键->查看页面信息 可以看到当前浏览器运行在何种模式(只能看到“混杂模式”和“标准规范模式”两种表示):

有位大神Henri Sivonen曾写过一篇文章叫做Activating Browser Modes with Doctype,里面包含了一个完整的表格,展示了各种DOCTYPE设置将会使浏览器以何种方式渲染。这里还有一篇秦歌的译文《用doctype激活浏览器模式》。

鉴于目前一些最新版本的浏览器已经放弃了准标准模式,所以关于准标准模式的细节这里就不再赘述了,感兴趣的同学可以详细阅读以下资料:

  • Gecko's "Almost Standards" Mode
  • Line Height Calculations in Almost Standards Mode
  • Images,Tables and Mysterious Gaps
  • almost-standards test
  • DOCTYPE Switches support in Opera Presto 2.10

那么,既然这么多的DOCTYPE都会触发非标准的模式,那么如何才能触发标准模式呢?对了!要使用HTML5 DOCTYPE,即:

 
  1. <!DOCTYPE html>

注意:如果文档中没有包含DOCTYPE或者包含了一个无法识别的DOCTYPE,则浏览器就会进入怪异模式。

下面简单说一下怪异模式。怪异模式有许多“怪异”的行为,主要是为了兼容那些遗留的古老页面而保留的模式。不同浏览器的怪异模式也不尽相同,它们都有自己的实现方式。怪异模式与标准模式的差异主要体现在 盒模型(box model)、表格单元格高度的处理等。例如IE的怪异模式中,元素的width包含了padding和border,而标准模式中padding和border 并不属于宽度的一部分。

若想详细了解浏览器在怪异模式下的行为,可以参看下面两篇文章。不过不建议在这上面花太多的精力,这是个历史遗留问题,而且我们也尽量保证新开发的页面不要进入到怪异模式:

  • Mozilla Quirks Mode Behavior
  • What happens in Quirks Mode?
  • Compatability Mode Test

小结:至此我们需要了解,浏览器有三种运行模式,即标准模式、准标准模式和怪异模式,要使用 <!DOCTYPE html> 来正确地触发标准模式。千万不要丢掉DOCTYPE声明,因为这会导致浏览器进入怪异模式。

IE的浏览器模式

IE8有4种模式:IE5.5怪异模式、IE7标准模式、IE8准标准模式和IE8标准模式,而IE9有7种模式: IE5.5怪异模式、IE7标准模式、IE8准标准模式、IE8标准模式、IE9准标准模式、IE9标准模式、XML模式。

其中XML模式是针对XML文档的,这里不打算阐述,细节可以看这篇文章[Defining Document Compatibility](http://msdn.microsoft.com/en-us/library/cc288325(v=vs.85).aspx) 中有详细阐述。

在IE8及以后的的IE浏览器中,支持X-UA-Compatible头,可以通过在服务器端设置HTTP头,或者在页面中插入<meta>标签来实现:

 
  1. HTTP:
  2. Header set X-UA-Compatible "IE=8"
  3. Meta:
  4. <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

这种方法主要是防止老的页面在较新的浏览器中显示不正常的情况的, 比如上面的代码可以强制IE8以上版本的浏览器以IE7的模式进行渲染。

注意,不要在新开发的网页中使用这种技术,这种技术只应该作为新老网页更替过程中的过渡方案。由于目前新开发的网页都是尽量支持最新版本的浏览器的,所以这种技术也会慢慢被淘汰,感兴趣的同学可以详细阅读 微软的这篇文档。

小结:这里我们需要知道有这种方式可以强制浏览器以某种模式运行,但只应作为过渡方案,不应在新开发的网页中使用。

IE9兼容性视图与IE9标准视图

如果你使用的是IE9,那么按下F12键就会出现开发者工具,上面有两个下拉菜单:浏览器模式和文档模式。那么什么是浏览器模式?什么又是文档模式?二者有何区别?

浏览器模式用于切换IE针对该网页的默认文档模式、对不同版本浏览器的条件注释解析、以及发送给网站服务器的用户代理(User-Agent)字符串的值。网站可以根据浏览器返回的不同用户代理字符串判断浏览器的版本和及安装的功能,这样就可以根据不同的浏览器返回不同的页面内容了。

文档模式用于指定IE的页面排版引擎(Trident)以哪个版本的方式来解析并渲染网页代码。切换文档模式会导致网页被刷新,但不会更改用户代理字符串中的版本号,也不会从服务器重新下载网页。切换浏览器模式的同时,浏览器也会自动切换到相应的文档模式。

一言以蔽之,浏览器模式会影响服务器端对客户端浏览器版本的判断,对条件注释也有影响;而文档模式会影响IE的排版引擎,对网页渲染会有影响,对CSS hack也会产生影响。因此,通过条件注释可以判断浏览器模式,而使用CSS hack可以判断文档模式。

如果我们使用一句简单的JavaScript语句来查看用户代理(User-Agent)字符串的值,则可以看到IE9兼容性视图与IE9的区别:

 
  1. <script type="text/javascript">
  2. alert('UA:'+navigator.userAgent);
  3. </script>

输出结果如下所示,注意其中的MSIE版本号已经不同。判断浏览器模式就是判断User-Agent中的版本号,即MSIE后面的数值:

 
  1. // IE9
  2. UA:Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)
  3. // IE9 兼容性视图
  4. UA:Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; Tablet PC 2.0)

话说IE9兼容性视图是模拟IE7的行为,那么IE9兼容性视图与IE7有没有区别呢?肯定是有区别的,即使是IE9中的IE7标准模式,与原生的IE7在渲染上也是有区别的,具体我们暂不去深究。

那么既然IE9兼容性视图的版本号跟IE7相同,如何才能判断当前是IE9兼容性视图,还是纯正的IE7呢?其实很简单,只需要判断浏览器的用户代理(User-Agent)字符串中是否包含Trident即可。首先检测MSIE的版本号是否为7.0,然后再判断是否含有Trident字串,若包含则为IE9兼容性视图,否则则为纯正的IE7。

小结:至此,你应该了解了什么是浏览器模式、什么是文档模式以及它们之间的区别了,另外还了解了IE9兼容性视图与IE9以及IE7的区别。

控制默认的渲染方式

当Internet Explorer 9遇到未包含X-UA-Compatible标头的网页时,它将使用<!DOCTYPE>指令来确定如何显示该网页。 如果该指令丢失或未指定基于标准的文档类型,则Internet Explorer 9将以IE5模式(怪异模式)来显示该网页。

如果<!DOCTYPE>指令指定了基于标准的文档类型,则Internet Explorer 9将以IE9模式显示该网页,但出现以下情况时除外:

  • 为该网页启用了兼容性视图。
  • 该网页是在Intranet区域中加载的,并且已将Internet Explorer 9配置为使用兼容性视图来显示Intranet区域中的网页。
  • 已将Internet Explorer 9配置为使用兼容性视图来显示所有网站。
  • 已将Internet Explorer 9配置为使用兼容性视图列表(其实是个黑名单,其中指定了一组始终使用兼容性视图显示的网站)。
  • 已使用开发人员工具覆盖在该网页中指定的设置。
  • 该网页遇到了页面布局错误,并且已将Internet Explorer 9配置为,通过在兼容性视图中重新打开网页来自动从此类错误中恢复。

此外,可以使用下面的注册表项来控制Internet Explorer对未包含X-UA-Compatible标头的页面的处理方式。

 
  1. HKEY_LOCAL_MACHINE (or HKEY_CURRENT_USER)
  2. SOFTWARE
  3. Microsoft
  4. Internet Explorer
  5. Main
  6. FeatureControl
  7. FEATURE_BROWSER_EMULATION
  8. iexplore.exe = (DWORD)

其中DWORD值必须等于下列值之一:

值    说明

7000 包含基于标准的 <!DOCTYPE> 指令的页面将以 IE7 模式显示。

8000 包含基于标准的 <!DOCTYPE> 指令的页面以 IE8 模式显示。

8888 页面始终以 IE8 模式显示,而不考虑 <!DOCTYPE> 指令。 (这可绕过前面列出的例外情况。)

关于IE浏览器确定文档模式的整个流程,可以参看这篇文章How IE8 Determines Document Mode,文中详细阐述了整个流程与内部机制。

小结:仍然坚持使用<!DOCTYPE html>,可最大程度减小发生错误的几率。

文档模式的检测

在JavaScript中可以通过documentMode来检测文档模式,在IE6和IE7中是使用compatMode来确定文档模式的,这个属性自IE8开始已经被documentMode所替代。

那么,如果需要兼容IE6和IE7的话(必须的 ...),则相应的检测代码大致如下:

 
  1. engine = null;
  2. if (window.navigator.appName == "Microsoft Internet Explorer")
  3. {
  4. // This is an IE browser. What mode is the engine in?
  5. if (document.documentMode) // IE8 or later
  6. engine = document.documentMode;
  7. else // IE 5-7
  8. {
  9. engine = 5; // Assume quirks mode unless proven otherwise
  10. if (document.compatMode)
  11. {
  12. if (document.compatMode == "CSS1Compat")
  13. engine = 7; // standards mode
  14. }
  15. // There is no test for IE6 standards mode because that mode
  16. // was replaced by IE7 standards mode; there is no emulation.
  17. }
  18. // the engine variable now contains the document compatibility mode.
  19. }

IE6和IE7中的compatMode有两个可能的值“CSS1Compat”和“BackCompat ”,分别对应了IE6和IE7中的标准模式和怪异模式。上面的代码首先假定是怪异模式,然后再试图推翻假设。这里没有包含“IE6 标准模式”,因为它已经被IE7标准模式所替代,没有模拟的情况。

这里要注意,不同的文档模式对JavaScript也有一些影响,我们不必去深究不同文档模式对JavaScript有何种不同影响,只需要在编码时进行特定的特性检测即可。

小结:一般情况下是没必要进行文档模式检测的,对于样式兼容我们可以写CSS hack,而对于JavaScript来说,则更加推荐特性检测,而不是检测浏览器本身。

浏览器模式与文档模式之间的关系

浏览器模式可以决定页面默认的文档模式,但文档模式可能会受其他因素影响而改变,如上文所述。如果浏览器模式与文档模式设置不同的话,会不会有什么影响呢?

我们已经知道浏览器模式主要用于标识浏览器本身,原则上不会对页面渲染产生影响。但是我们又知道,浏览器模式可以影响条件注释,所以如果你的页面中有条件注释的话,那么浏览器模式的变化就会影响到页面渲染。

服务器端只能通过浏览器模式所标识的版本来确定客户端浏览器的版本,如果你将浏览器模式标识为IE9,但文档模式选择为IE7标准的话,就可能会有问题。不过这还要看服务器端是否有针对不同浏览器的处理策略,如果服务器端并未对不同浏览器的输出做差异化处理的话,那么这两个模式选项不同就不会有问题。

小结:如果服务器端对不同浏览器的输出做了差异化处理,那么浏览器模式和文档模式不一致就可能产生问题。

结语

本文参考了大量现有文献,详细阐述了各种模式的区别以及它们之间的关系。相信通过上面的叙述,你已经能够区分这些浏览器模式或者文档模式以及它们之间的关系了,每节的结论在小结中已有阐述,希望能够对你有所帮助。

深入理解浏览器兼容性模式相关推荐

  1. IE浏览器兼容性模式

    最近支持公司的一个内部业务管理系统,系统是基于jQuery来实现:用了2年的MVVM框架的我转向这个完全使用jQuery框架来开发的系统,真是相当不爽(相信用过MVVM框架的跟我是相同的感受):更为憋 ...

  2. 【F12一下,看看页面里的第一行】——说说浏览器兼容性模式

    面试官:请你谈谈标准(Standards)模式.怪异(Quirks)模式.准标准(Almost Standards)模式,当你打开IE9时候会看见,浏览器模式,文档模式,兼容性视图,这些又是什么? 尼 ...

  3. 有哪些浏览器兼容性测试,如何做好兼容性测试工作?

    一个软件产品或者程序需要在不同浏览器上使用,兼容不同浏览器版本,听起来是一件复杂的事情.以我们熟知的主流浏览器就有很多版本,比如火狐浏览器.谷歌浏览器.IE浏览器等,想要软件产品或者程序在这些浏览器上 ...

  4. 浏览器兼容性问题与浏览器的内核及渲染模式

    兼容性问题 目前市面上流行的浏览器有多种,这些浏览器在处理一个相同的页面时,表现或行为有时会有差异.这种差异可能很小,甚至不会被注意到:也可能很大,甚至造成在某个浏览器下无法正常浏览.我们把引起这些差 ...

  5. 360安全浏览器兼容模式怎么设置_测试新手一定要知道:最实用的Web兼容性测试经验都在这...

    在日常工作中,我们经常碰到网页不兼容的问题.我们之所以要做兼容性测试,目的在于保证待测试项目在不同的操作系统平台上正常运行. 主要包括待测试项目能在同一操作系统平台的不同版本上正常运行:待测试项目能与 ...

  6. IE浏览器确定兼容性模式

    HTML:<html>      <head>      <!-- Mimic Internet Explorer 7 -->         <title& ...

  7. html5谷歌浏览器兼容性,谷歌浏览器怎样打开兼容模式_google浏览器兼容性设置在哪-win7之家...

    google谷歌浏览器是现在目前最流行的浏览工具之一,但是在浏览的时候,大部分网页都要兼容模式才可以打开,那么就需要设置兼容模式,很多用户可能还不知道google浏览器兼容性设置在哪吧,为了帮助到大家 ...

  8. flex与相对定位在国内双核浏览器极速模式下的兼容性问题

    在国内的浏览器中,360浏览器,QQ浏览器等绝大部分都是双核浏览器.双核浏览器即拥有IE兼容内核和非IE极速内核两个内核,分别对应兼容模式和极速模式.兼容模式时使用IE内核,极速模式采用webkit内 ...

  9. html网页自动兼容模式,解决CSS浏览器兼容性问题的4种方案

    前端是一个苦逼的职业,不仅因为技术更新快,而且要会的东西实在太多了,更让人头疼的是,还要面临各种适配.兼容性问题. 为什么会有浏览器兼容性问题? 还不是因为浏览器厂商太多了! Chrome,Frire ...

最新文章

  1. C++尽可能使用const
  2. linux进程cpu资源分配命令nice,renice,taskset
  3. Java:从Java 8开始受益于内联类属性
  4. python王者归来 pdf_OpenStack开源云:王者归来 PDF 下载
  5. 厉害了,这个省未来5年将投入63亿人民币扶持博士博士后!
  6. 图像识别开源代码_灰度图像着色开源代码
  7. BZOJ 1070: [SCOI2007]修车(最小费用最大流)
  8. 关于Maven的插件maven-dependency-plugin
  9. 驱动等待队列,poll和select编程
  10. 南邮ctf mysql_南邮ctf知识点汇总 - Crypto篇
  11. python扫雷脚本_Python自动扫雷实现方法
  12. android 透明栏,Android状态栏透明(沉浸式效果)
  13. Atitit. 二进制数据ascii表示法,与base64编码解码api 设计标准化总结java php c#.net...
  14. 华为HG255d刷石像鬼OpenWrt,体验强大的QOS功能
  15. 实用技巧----百度绘制函数图像
  16. 谷歌play支付_Google Play的新功能
  17. php商城伪静态,友价商城nginx伪静态源码规则
  18. xx壳通过外网远程访问本地SQLServer服务器(原创)
  19. 微信小程序真机调试功能失常
  20. 如何keil4下面创建工程?

热门文章

  1. 微信第三方登录,主要手机没有安装微信处理
  2. 轻便简洁的电脑录音软件,免费收藏!
  3. SNMP 枚举工具 Snmpwalk
  4. 用wxBot和图灵机器人API实现微信群聊机器人
  5. dw html 浮动窗口,Dreamweaver怎样实现飘浮光球特效
  6. Docker镜像常用命令
  7. Ubuntu 配置亚马逊 aws cli 上传文件文件夹至 亚马逊 AWS S3
  8. 2022-02-15:扫地机器人。 房间(用格栅表示)中有一个扫地机器人。 格栅中的每一个格子有空和障碍物两种可能。 扫地机器人提供4个API,可以向前进,向左转或者向右转。每次转弯90度。 当扫地机
  9. MGRE环境下的OSPF (实验超详解)
  10. 火焰纹章核心功能的实现