黄锦诚的个人博客--有志者是锦诚!

关于浏览器的标准模式与怪异模式

  早几天与一业内的面试官通电,他问了一些前端的相关知识。当然,问的问题有多个,也无法一下子一一进行深入的学习和探讨,只能一个个的来进行罗列。其中一个印象比较深刻的是善于标准模式和怪异模式。之前是有听过这个东西,但没有过深入一点的学习和探讨,借此机会,我也来进行好好的复习一下。

  有时候做的页面是好好的,但加了程序后,页面就会出现一些莫名其妙的奇怪的现象,如某些JS的计算(宽度、高度、坐标位置等)出现问题,查语法、看思路都没有问题,最后进行源文件和加程序后的页面对比,发现将文档声明前的程序去掉就好了。其实这个就是问题的根源所在了,因为文档声明前加了程序,导致页面进入了怪异模式,所以有时候也很有必要对标准模式和怪异模式进行一个研究。

  以下部分内容为来算网络加个人的一些整理:

标准模式与怪异模式:

  由于历史的原因,各个浏览器在对页面的渲染上存在差异,甚至同一浏览器在不同版本中,对页面的渲染也不同。在W3C标准出台以前,浏览器在对页面的渲染上 没有统一规范,产生了差异(Quirks mode或者称为Compatibility Mode);由于W3C标准的推出,浏览器渲染页面有了统一的标准(CSScompat或称为Strict mode也有叫做Standars mode),这就是二者最简单的区别。

  W3C标准推出以后,浏览器都开始采纳新标准,但存在一个问题就是如何保证旧的网页还能继续浏览,在标准出来以前,很多页面都是根据旧的渲染方法编写的, 如果用的标准来渲染,将导致页面显示异常。为保持浏览器渲染的兼容性,使以前的页面能够正常浏览,浏览器都保留了旧的渲染方法(如:微软的IE)。这样浏 览器渲染上就产生了Quircks mode和Standars mode,两种渲染方法共存在一个浏览器上。

  火狐一直工作在标准模式下,但IE(6,7,8)标准模式与怪异模式差别很大,主要体现在对盒子模型的解释上,这个很重要,下面就重点说这个。

 

  那么浏览器究竟该采用哪种模式渲染呢?这就引出的DTD,既是网页的头部声明,浏览器会通过识别DTD而采用相对应的渲染模式:

  1. 浏览器要使老旧的网页正常工作,但这部分网页是没有doctype声明的,所以浏览器对没有doctype声明的网页采用quirks mode解析。
  2. 对于拥有doctype声明的网页,什么浏览器采用何种模式解析,这里有一张详细列表可参考:http://hsivonen.iki.fi/doctype/
  3. 对于拥有doctype声明的网页,这里有几条简单的规则可用于判断:对于那些浏览器不能识别的doctype声明,浏览器采用strict mode解析
  4. 在doctype声明中,没有使用DTD声明或者使用HTML4以下(不包括HTML4)的DTD声明时,基本所有的浏览器都是使用quirks mode呈现,其他的则使用strict mode解析。
  5. 可以这么说,在现有有doctype声明的网页,绝大多数是采用strict mode进行解析的。
  6. 在ie6中,如果在doctype声明前有一个xml声明(比如:<?xml version=”1.0″ encoding=”iso-8859-1″?>),则采用quirks mode解析。这条规则在ie7中已经移除了。

  许多HTML编辑器会自动添加DOCTYPE声明。如果创建XHTML文档,它们还可能在DOCTYPE声明前面添加XML声明:

  浏览器根据DOCTYPE是否存在以及使用的DTD来选择要使用的表现方法。如果XHTML文档包含形式完整DOCTYPE,那么它一般以标准模式 表现。对于HTML 4.01文档,包含严格DTD的DOCTYPE常常导致页面以标准模式表现。包含过渡DTD和URI的DOCTYPE也导致页面以标准模式表现,但是有过 渡DTD而没有URI会导致页面以怪异模式表现。DOCTYPE不存在或形式不正确会导致HTML和XHTML文档以怪异模式表现。

  根据DOCTYPE是否存在选择表现方法的效果被称为DOCTYPE切换(DOCTYPE switching)或DOCTYPE侦测(DOCTYPE sniffing)。并非所有浏览器都采用这些规则,但是这些规则很好地说明了DOCTYPE切换的工作方式。Eric Meyer深入研究了这个主题,并且制作了一张图表(http://meyerweb.com/eric/dom/dtype/dtype- grid.html),或点击此处打开,来说明不同的浏览器如何根据DOCTYPE声明选择表现方法。

  XML声明是XML文件使用的可选声明,它定义使用的XML版本和字符编码类型等设置。不幸的是,如果DOCTYPE声明不是页面上的第一个元素,那么IE 6会自动切换到怪异模式。因此,除非要将页面用做XML文档,否则最好避免使用XML声明

  DOCTYPE切换是浏览器用来区分遗留文档和符合标准的文档的手段。无论是否编写了有效的CSS,如果选择了错误的DOCTYPE,那么页面就将以怪 异模式表现,其表现就可能会有错误或不可预测。因此,一定要在站点的每个页面上包含形式完整的DOCTYPE声明,并且在使用HTML时选择严格的 DTD。

如何设置为怪异模式:

  1、无doctype声明、定义旧的HTML版本(HTML4以下,例如3.2)
  2、加XML声明,可在ie6下触发
  <?xml version=”1.0″ encoding=”utf-8″?>
  <!DOCTYPE …>
  3、在XML声明和XHTML的DOCTYPE之间加入HTML注释,可在ie7下触发 <?xml version=”1.0″ encoding=”utf-8″?>
  <!– keep IE7 in quirks mode –>
  <!DOCTYPE …>
  4、<!—>放在<!DOCTYPE前面

  这里有一张详细列表可参考:http://hsivonen.iki.fi/doctype/

如何设置为标准模式:

  加入以下任意一种:

  HTML4提供了三种DOCTYPE可选择:

  <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Transitional//EN” “http://www.w3.org/TR/html4/loose.dtd“>
  <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN” “http://www.w3.org/TR/html4/strict.dtd“>
  <!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01 Frameset//EN” “http://www.w3.org/TR/html4/frameset.dtd“>

  XHTML1.0提供了三种DOCTYPE可选择:

  (1)过渡型(Transitional )
  <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd“>

  (2)严格型(Strict )
  <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Strict//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd“>

  (3)框架集型(Frameset )
  <!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Frameset//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd“>

  这里有一张详细列表可参考:http://hsivonen.iki.fi/doctype/

如何判定现在是标准模式还是怪异模式:

  方法一:执行以下代码

alert(window.top.document.compatMode) ;

//BackCompat  表示怪异模式
//CSS1Compat  表示标准模式

方法二:jquery为我们提供的方法,如下:
alert($.boxModel)
alert($.support.boxModel)

  IE6,7,8浏览器的标准模式还是怪异模式 盒子模型的 差异

  (由于火狐的始终表现的很一致,不种我们操心。所以这里我们重点说IE浏览器)

深化扩展:

  怪异模式对开页面的影响个人估计并不大,因为目前普遍人们都不再使用太旧的版本的浏览器,当然IE6是比较特殊的一个,但怪异模式对于JS的计算影响估计会比较大些,下面就一些安全进行分析。

————————————————-模态窗口—————————————————-

  我们想做一个DIV蒙层,中间放一个iframe,做一个像模态窗口的dialog工具

思路如下:

  取出页面 网页可见区域 的宽与高, 进行蒙层,

  通过CSS的固定定位属性{position:fixed}来实现,可以让HTML元素脱离文档流固定在浏览器的某个位置,

  这样拖动滚动条时, 蒙层不会移动,一直在中心位置。

  中心位置放一个iframe,用来显示其它网页,并可以提交表单。

  可以用以下代码计算 蒙层的宽与高:

Js代码>

  //计算窗口的高宽和滚动条的位置
  alert(window.top.document.compatMode) ;//区分怪异模式或标准模式
  var cw = window.top.document.compatMode == “BackCompat” ?window.top.document.body.clientWidth:window.top.document.documentElement.clientWidth;//窗体高度
  var ch = window.top.document.compatMode == “BackCompat” ?window.top.document.body.clientHeight:window.top.document.documentElement.clientHeight;//窗体宽度//必须考虑文本框处于页面边缘处,控件显示不全的问题
  var sw = Math.max(window.top.document.documentElement.scrollLeft, window.top.document.body.scrollLeft);//横向滚动条位置
  var sh = Math.max(window.top.document.documentElement.scrollTop, window.top.document.body.scrollTop);//纵向滚动条位置//考虑滚动的情况

  alert(“cw:”+cw+”  ch:”+ch+”  sw:”+sw+”  sh”+sh);

————————————–参考 1—————————————————–

我们先来认识一下有哪些属性可以使用:

scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离
scrollTop:设置或获取位于对象最顶端和窗口中可见内容的最顶端之间的距离
scrollWidth:获取对象的滚动宽度
scrollHeight: 获取对象的滚动高度。

obj.offsetTop 指 obj 相对于版面或由 offsetParent 属性指定的父坐标的计算上侧位置,整型,单位像素。
obj.offsetLeft 指 obj 相对于版面或由 offsetParent 属性指定的父坐标的计算左侧位置,整型,单位像素。
obj.offsetWidth 指 obj 控件自身的绝对宽度,不包括因 overflow 而未显示的部分,也就是其实际占据的宽度,整型,单位像素。
obj.offsetHeight 指 obj 控件自身的绝对高度,不包括因 overflow 而未显示的部分,也就是其实际占据的高度,整型,单位像素

event.clientX 相对文档的水平座标
event.clientY 相对文档的垂直座标
event.offsetX 相对容器的水平坐标
event.offsetY 相对容器的垂直坐标

clientWidth  内容可视区域的宽度
clientHeight 内容可视区域的高度
clientTop    内容可视区域相对容器的垂直坐标
clientLeft   内容可视区域相对容器的水平坐标

参考图片:

———————————————-参考 2—————————————————–

js代码

  var Width_1=document.body.scrollWidth;    //body滚动条总宽
  var Height_1=document.body.scrollHeight;  //body滚动条总高
  var Width_2=document.documentElement.scrollWidth;    //documentElement滚动条总宽
  var Height_2=document.documentElement.scrollHeight;  //documentElement滚动条总宽
  //——————————
  var Width_3=document.body.clientWidth;   //body网页可见区域宽,滚动条隐藏部分不算
  var Height_3=document.body.clientHeight; //body网页可见区域高,滚动条隐藏部分不算
  var Width_4=document.documentElement.clientWidth;   //documentElement网页可见区域宽,滚动条隐藏部分不算
  var Height_4=document.documentElement.clientHeight; //documentElement网页可见区域高,滚动条隐藏部分不算
  //——————————
  var Width_5=window.screen.availWidth;  //屏幕可用工作区宽度(用处不大)
  var Height_5=window.screen.availHeight;//屏幕可用工作区高度
  //——————————
  var scrollLeft_7=window.top.document.body.scrollLeft;//body水平滚动条位置
  var scrollTop_7=window.top.document.body.scrollTop;//body垂直滚动条位置
  var scrollLeft_8=window.top.document.documentElement.scrollLeft;//documentElement水平滚动条位置
  var scrollTop_8=window.top.document.documentElement.scrollTop;//documentElement垂直滚动条位置
  alert(” body滚动条总宽:”+Width_1+”,body滚动条总高:”+Height_1+”,\n documentElement滚动条总宽:”+Width_2+”,documentElement滚动条总高:”+Height_2+”,\n”+”\n body网页可见区域宽:”+Width_3+”,body网页可见区域高:”+Height_3+”,\n documentElement网页可见区域宽:”+ Width_4+”,documentElement网页可见区域高:”+Height_4+

“,\n”+”\n 屏幕可用工作区宽度:”+Width_5+”, 屏幕可用工作区高度:”+Height_5+”,\n”+”\n body水平滚动条位置:”+scrollLeft_7+”,body垂直滚动条位置:”+scrollTop_7+”,\n documentElement水平滚动条位置:”+scrollLeft_8+”,documentElement垂直滚动条位置:”+scrollTop_8);

  (需要提一下:CSS中的margin属性,与clientWidth、offsetWidth、clientHeight、offsetHeight均无关)
  下面是从w3school查到的,说的不是很详细

  根节点
  有两种特殊的文档属性可用来访问根节点:

document.documentElement
document.body
  第一个属性可返回存在于 XML 以及 HTML 文档中的文档根节点。

  第二个属性是对 HTML 页面的特殊扩展,提供了对 <body> 标签的直接访问。

http://www.w3school.com.cn/htmldom/dom_nodes_access.asp

  收集整理于互联网

  参考:

  http://cavonchen.javaeye.com/blog/738423

  http://hsivonen.iki.fi/doctype/

  现在几乎人人都用标准的doctype来声明文档,所以纠结标准、怪异模式对工作的影响不太大,本文仅作一个个人的扫盲文章存档。

  以上是简单收集整理的一些资料,也许不完整,甚至还有错误的地方,欢迎大方指正。



2条评论

  1. 我很二说道:

    (3)框架型(Frameset )
    这里是框架集型,不是框架型。二者不可同一而论!



发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

黄锦诚 腾讯微博
黄锦诚,专注前端、分享生活、记录工作、关于一切,这里有不一样的惊喜!

分类

Wopus主机优惠码

无觅相关文章插件,快速提升流量