DOCTYPE:文档类型与浏览器模式

浏览器打开页面时,先看文档第一行的 <!DOCTYPE>,再决定按现行 HTML、CSS 规范排,还是按当年 Netscape Navigator、Internet Explorer 的老行为排。声明写错、写残或干脆不写,同一套 CSS 在不同引擎里会对不上。它不是一个带结束标签的 HTML 元素,而是写在文档最顶端的声明指令。

文档类型定义(DTD)

DTD(Document Type Definition,文档类型定义)是一套语法规则,用来定义 XML 或 (X)HTML 的文件类型:允许哪些元素、它们有哪些属性、彼此如何嵌套。

在 SGML、XML 体系里,解析器可以拿 DTD 做合法性验证。浏览器对 HTML 并不去下载那份 DTD 做校验,而是根据 <!DOCTYPE> 字符串切换渲染模式。

DTD 理论上能定义整个 SGML 语族的文档类型,规则又长又繁。后来更流行的是 XML 和 HTML,不再把完整 DTD 挂在每个页面前面。

什么是 SGML

SGML标准通用标记语言(Standard Generalized Markup Language),是国际上定义电子文件结构和内容描述的标准。它不是一门具体的标记语言,而是一门「元语言」(Metalanguage):用来定义其他标记语言的语言。HTML 4.01 及更早的 HTML 是按 SGML 来定义的;HTML5 已经不基于 SGML。

SGML 的三个组成部分:

  • SGML 声明(SGML Declaration):指定构建文档的基本参数。
  • 文档类型定义(DTD):这是 SGML 的核心。DTD 定义一门新语言的合法「语法」,用一系列规则明确规定文档中可以有哪些元素、如何嵌套,以及哪些属性是必要的。
  • 文档实例(Document Instance):实际撰写的、包含数据和标记的文档文件。

DOCTYPE 的作用

DOCTYPE 是 Document Type(文档类型)的简写,完整说法是文档类型声明(Document Type Declaration)。它用来声明文档类型和所依据的 DTD 规范,历史上承担两件事:文件的合法性验证,以及告诉浏览器按哪套规则解析文档

在 HTML 源码里,<!DOCTYPE> 严格说来不是一个 HTML 标签,只是一条声明指令,用来告诉浏览器当前这份代码按哪一种 HTML 或 XHTML 规范来理解。

<!DOCTYPE> 真正决定浏览器以标准模式接近标准模式还是怪异模式来解析文档。

做页面时必须让浏览器知道这份 HTML 用的是哪一种规范,显示才会按现行规则走。没有声明时,浏览器按怪异模式解析;各浏览器的怪异模式并不相同(按各自内置的旧排版规则),同一份页面在不同浏览器里会排出不一样的结果。

DOCTYPE 组成部分

HTML 4、XHTML 时代的完整声明可以拆成下面几段。HTML5 的 <!DOCTYPE html> 不再带这些字段。

<!DOCTYPE 根元素 可用性 "注册//组织//类型 标签 定义//语言" "URL">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
  • 根元素:指定 DTD 中声明的顶级元素类型,这与声明的 SGML 文档类型相对应,默认 HTML
  • 可用性:指定正式公开标识符(FPI,Formal Public Identifier)是可公开访问的对象还是系统资源。默认 PUBLIC,表示可公开访问。SYSTEM 表示系统资源,如本地文件或 URL。
  • 注册:指定组织是否由国际标准化组织(ISO)注册。默认 +,组织名称已注册。- 表示组织名称未注册。IETF 和 W3C 都不是注册的 ISO 组织,所以常见写法以 -// 开头。
  • 组织:指定负责创建和维护该 DTD 的团体或组织名称,即 OwnerID。常见是 IETF 或 W3C。有的资料写成 OwnderID,那是拼写错误。
  • 类型:指定公开文本类,即所引用的对象类型。默认 DTD
  • 标签:指定公开文本描述,即对所引用公开文本的唯一描述性名称,后面可附带版本号。默认 HTML
  • 定义:指定文档类型定义。Strict(排除所有 W3C 希望逐步淘汰的表现性属性和元素)、Transitional(包含除 frameset 之外的全部内容)、Frameset(框架集文档)。
  • 语言:指定公开文本语言,即编写所引用对象时用的自然语言编码。按 ISO 639 写成两个大写字母。默认 EN
  • URL:指定所引用对象的位置,也叫系统标识符(System Identifier)。有无这一段,会改变部分旧 DOCTYPE 触发的是怪异模式还是接近标准模式,见后文。

DOCTYPE 的用法

  • 写在 <html> 之前。
  • 必须放在文档最顶部,在所有代码和标识之上。HTML、XHTML 都一样。旧版 IE 里,若在它前面插了注释、XML 声明(<?xml version="1.0"?>)或 BOM,仍会掉进怪异模式。
  • 没有结束标签。
  • 在 HTML 语法里对大小写不敏感,<!DOCTYPE html><!doctype html> 效果相同。作为 application/xhtml+xml 解析的 XHTML 按 XML 规则处理,声明要符合 XML。
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Document</title>
    </head>
    <body>
        hello world
    </body>
</html>

常用 DOCTYPE 声明

HTML 里常见的 <!DOCTYPE> 声明类型共有 8 种:HTML5 1 种,HTML 4.01 和 XHTML 1.0 各 3 种,XHTML 1.1 1 种。

HTML5 <!DOCTYPE> 声明

HTML5 只规定一种声明,能向前、向后兼容,代码也更简洁。HTML5 不是基于 SGML,因此不要求引用 DTD。现行页面推荐这一条。

<!DOCTYPE html>

IE 6 也会把它当成标准模式。新项目没有理由再写更长的 DOCTYPE。

HTML 4.01 <!DOCTYPE> 声明

HTML 4.01 规定了三种不同的 <!DOCTYPE> 声明:

  • Strict:包含所有 HTML 元素和属性,但不包括展示性的和弃用的元素(比如 font)。不允许框架集(Framesets)。
  • Transitional:包含所有 HTML 元素和属性,包括展示性的和弃用的元素(比如 font)。不允许框架集(Framesets)。
  • Frameset:等同于 HTML 4.01 Transitional,但允许框架集内容。
<!--HTML 4.01 Strict-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

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

<!--HTML 4.01 Frameset-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">

XHTML 1.0 <!DOCTYPE> 声明

XHTML 1.0 也规定了三种不同的 <!DOCTYPE> 声明:

  • Strict:包含所有 HTML 元素和属性,但不包括展示性的和弃用的元素(比如 font)。不允许框架集(Framesets)。必须以格式正确的 XML 来编写标记。
  • Transitional:包含所有 HTML 元素和属性,包括展示性的和弃用的元素(比如 font)。不允许框架集(Framesets)。必须以格式正确的 XML 来编写标记。
  • Frameset:等同于 XHTML 1.0 Transitional,但允许框架集内容。
<!--XHTML 1.0 Strict-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<!--XHTML 1.0 Transitional-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<!--XHTML 1.0 Frameset-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">

XHTML 1.1 <!DOCTYPE> 声明

XHTML 1.1 规定了一种声明,等同于 XHTML 1.0 Strict,但按模块化(Modularization)组织,允许按模块增减能力。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">

其他 <!DOCTYPE> 声明

这些更旧或更窄的声明,现行浏览器多半仍能用来切换模式,新页面不必再用。

<!-- HTML 4.0 Strict -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/html4/strict.dtd">

<!-- HTML 4.0 Frameset -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">

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

<!-- HTML 3.2 -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">

<!-- HTML 2.0 -->
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">

<!-- XHTML Basic 1.0 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.0//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic10.dtd">

<!-- XHTML Basic 1.1 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">

<!-- XHTML 2.0 -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 2.0//EN" "http://www.w3.org/MarkUp/DTD/xhtml2.dtd">

上面 HTML 4.0 三条里的系统标识符沿用了 html4/ 路径,实际对应的是后来 HTML 4.01 的 DTD 文件;HTML 4.0 当年的路径是 http://www.w3.org/TR/REC-html40/。XHTML 2.0 没有成为继任标准,工作已被 HTML5 取代。有的资料会把 Basic 1.1 的 DTD 也标成 1.0。

命名空间 namespace

<html xmlns="http://www.w3.org/1999/xhtml">

xmlns 是 XML namespace 的缩写,称为命名空间。它在 XHTML 中是必要的,在 HTML 中则是可选的。以 text/html 发送的 HTML5 里,根元素始终处于 HTML 命名空间,xmlns 写了也不改变解析方式;内嵌的 SVG、MathML 靠 HTML 解析器的外文内容规则识别。以 application/xhtml+xml 发送的 XHTML 必须按 XML 带上命名空间。

XHTML 是 HTML 向 XML 过渡的标记语言,需要符合 XML 文档规则,因此也需要定义命名空间。XHTML 1.0 不能自定义元素名,所以它的命名空间都相同,就是 http://www.w3.org/1999/xhtml

xmlns 属性可以在文档中定义一个或多个可供选择的命名空间,可以放置在文档内任何元素的开始标签中。

xmlns 提供避免元素命名冲突的方法。XML 中的元素名称是由开发者定义的,当两个不同的文档使用相同的元素名时,就会发生命名冲突。

如果需要使用符合 XML 规范的 XHTML 文档,则应该在文档中的 <html> 标签中至少使用一个 xmlns 属性,以指定整个文档所使用的主要命名空间:

<html xmlns="http://www.w3.org/1999/xhtml">

如果需要在一个 div 元素中显示一串数学公式,则可以为该 div 元素定义一个数学命名空间。比如这样(示意默认命名空间怎么挂到子树上;真正排版公式应使用 MathML 元素,而不是把普通 div 改个命名空间):

<div xmlns="http://www.w3.org/1998/Math/MathML">x3/x</div>

如果不希望在每次显示除法公式时都在 div 元素中定义 xmlns 属性,那么更好的办法是在文档的开头处定义具有前缀的命名空间:

<html xmlns="http://www.w3.org/1999/xhtml" xmlns:math="http://www.w3.org/1998/Math/MathML">

然后就可以在子元素上使用该前缀了,就像这样:

<math:div>x3/x</math:div>

这只说明「前缀 + 本地名」怎么写。合法 MathML 根元素是 math,不是 div。MathML 的命名空间是 http://www.w3.org/1998/Math/MathML(注意是 1998,且 MathML 大小写如此)。有的资料写成 http://www.w3.org/1999/Math/MathMl,地址和大小写都不对。

常用的命名空间值:

  • HTML:http://www.w3.org/1999/xhtml
  • MathML:http://www.w3.org/1998/Math/MathML。MathML 指数学标记语言,是 XML 语言的一个子集,用来在 Web 网页,甚至部分软件中显示数学公式。简言之,就是使用特殊的类似 HTML 的标记在网页中显示数学公式。
  • SVG:http://www.w3.org/2000/svg
  • XLink:http://www.w3.org/1999/xlink。有的资料写成 xllink。XLink 是一种通过 W3C 推荐标准 认证的 XML 标记语言,用于在 XML 文档中创建超链接,以及提供与这些链接相关联的元数据。
  • xml:http://www.w3.org/XML/1998/namespace。这是 XML 规范预留的 xml: 前缀所属命名空间,例如 xml:langxml:id,不必、也不应自己再声明一遍 xmlns:xml
  • xmlns:http://www.w3.org/2000/xmlns/。这是 xmlnsxmlns: 前缀本身所属的命名空间,由 XML 命名空间规范保留,页面里不要用它当普通元素的命名空间。

怪异模式和标准模式

很久以前的网页通常要准备两个版本:给网景(Netscape)Navigator 的,以及给微软(Microsoft)Internet Explorer 的。W3C 把网络标准立起来之后,浏览器不能直接丢掉那些已经上线的老站。于是引擎同时保留两套(后来是三套)排版行为,用 DOCTYPE 把「按新规范写的站」和「按老浏览器写的站」分开。

目前浏览器的排版引擎使用三种模式:

  • 怪异模式(quirks mode):排版会模拟 Navigator 4 与 Internet Explorer 5 的非标准行为,用来撑起网络标准普及之前就建好的网站。
  • 标准模式(standards mode,现行规范称 no-quirks mode):行为按现行 HTML 与 CSS 规范来。
  • 接近标准模式(almost standards mode,现行规范称 limited-quirks mode):只实现极少数怪异行为,主要是表格单元格里图片的行高、基线对齐,避免单元格底部多出一条缝。

浏览器如何决定使用哪个模式

对 HTML 文件来说,浏览器使用文件开头的 DOCTYPE 来决定用哪一种模式。以 application/xhtml+xml 发送的真正 XHTML 按 XML 解析,不靠这段声明在怪异、标准之间切换。

以下情况浏览器会采用标准模式(no-quirks)渲染:

  • 给出了完整且会触发标准模式的 DOCTYPE,例如 HTML5 的 <!DOCTYPE html>
  • DOCTYPE 声明了 Strict DTD(如 HTML 4.01 Strict、XHTML 1.0 Strict)

以下情况浏览器会采用接近标准模式(limited-quirks)渲染:

  • DOCTYPE 声明了 Transitional 或 Frameset DTD,并且给出了 URI(系统标识符)

以下情况浏览器会采用怪异模式(quirks)渲染:

  • DOCTYPE 声明了 Transitional 或 Frameset DTD 但未给出 URI
  • DOCTYPE 声明不合法
  • 未给出 DOCTYPE 声明

有的资料把「Transitional DTD 且带 URI」也归进标准模式。现行引擎里它走的是接近标准模式:document.compatMode 仍是 CSS1Compat,和标准模式无法用这一属性区分,差别主要在表格单元格里的图片布局。

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Hello World!</title>
    </head>
    <body>
    </body>
</html>

<!DOCTYPE html> 是所有可用的 DOCTYPE 之中最简单的,也是 HTML5 所推荐的。HTML 的早期变种也曾是推荐标准,不过当今的浏览器都会对这个 DOCTYPE 使用标准模式,就算是早已过时的 Internet Explorer 6 也一样。目前没有正当理由去使用其他更复杂的 DOCTYPE。若使用其他 DOCTYPE,会面临触发接近标准模式或者怪异模式的风险。

在 HTML5 中,DOCTYPE 唯一的作用是启用标准模式。更早期的 HTML 标准中,DOCTYPE 还会指向一份 DTD,供校验器核对合法性。浏览器并不会去拉那份 DTD 做校验,也不会把 DOCTYPE 用在渲染模式切换以外的用途。

怪异模式和标准模式的不同点

盒模型的处理差异

标准 CSS 盒模型的宽度和高度等于内容区的宽度和高度,不包含内边距和边框(即默认的 content-box)。

IE 5 以及怪异模式下的旧 IE 把内边距和边框算进 widthheight,接近后来的 box-sizing: border-box

因此,IE 5.5 及以下,以及其他版本处于怪异模式时,和标准模式下的盒模型宽高计算方式不一样。IE 6 起,有正确 DOCTYPE 时按标准内容盒计算。

行内元素的垂直对齐

很多早期的浏览器把图片对齐到包含它们的盒子的下边框,虽然 CSS 规范要求它们对齐到盒内文本的基线。

标准模式下,基于 Gecko 的浏览器会对齐到基线,而在怪异模式下会对齐到底部。

最直接的例子就是图片的显示。在标准模式下,图片并不是与父元素的下边框对齐的,如果仔细观察,你会发现图片与父元素下边框之间存在一点小空隙。那是因为标准模式下,图片是基线对齐的。而怪异模式下,则不存在这个问题。接近标准模式保留的,主要也是表格单元格里这一条。

获取视口尺寸

// 标准模式下,任意浏览器都兼容:
document.documentElement.clientWidth
document.documentElement.clientHeight

// 怪异模式下的浏览器:
document.body.clientWidth
document.body.clientHeight

怪异模式量客户区、读 scrollTop 要用 document.body。标准模式要用 document.documentElement<html>)。

行内元素的高宽

在标准模式下,给 span 等行内元素设置 widthheight 都不会生效,而在怪异模式下则会生效。

百分比的高度

在标准模式下,一个元素的高度是由其包含的内容来决定的,如果父元素没有设置高度,子元素设置一个百分比的高度是无效的。怪异模式下,旧 IE 对 htmlbody 的百分比高度更宽松。

margin: 0 auto 水平居中

使用 margin: 0 auto 在标准模式下可以使元素水平居中,但在旧 IE 的怪异模式下会失效。解决办法是用父元素的 text-align 属性。

图片的 padding

旧 IE 的怪异模式下,给图片设置 padding 会失效。

表格中的字体继承

旧 IE 的怪异模式下,table 中的字体属性不能继承上层的设置。

white-space: pre

旧 IE 的怪异模式下,white-space: pre 会失效。

相关问题

为什么 HTML5 只需要写简短的一句

HTML 4.01 及更早是基于 SGML 定义的,所以要加上 DTD 的引用。

HTML5 不基于 SGML,因此不需要对 DTD 进行引用,但是需要 DOCTYPE 来规范浏览器的行为,让浏览器按照它们应该的方式来运行(进入标准模式)。

如何查看目前是哪个模式

  • 用 JavaScript 判断是哪种模式。

    document.compatMode
    // BackCompat:怪异模式
    // CSS1Compat:标准模式或者接近标准模式
    

    CSS1Compat 无法区分标准模式和接近标准模式。

  • 在 Firefox 中,请从右键菜单选择「查看页面信息」,然后查看「渲染模式」。

  • 在 Internet Explorer 中,请按下 F12,然后查看「文档模式」。

结语

现行页面在第一行写 <!DOCTYPE html>,引擎就会走标准模式。DOCTYPE 不再负责把 DTD 拉下来做校验,只负责把排版从旧浏览器的兼容行为里切出来。遇到对不齐的盒模型、图片底下一条缝、clientWidth 读错节点,先看有没有声明、声明会不会掉进怪异模式或接近标准模式。

参考资料

MDN 怪异模式和标准模式

HTML Standard:The DOCTYPE

© lizhao all right reserved,powered by Gitbook文件修订时间: 2026-08-25 23:59:58

results matching ""

    No results matching ""