DOCTYPE 有什么用?标准模式和怪异模式有什么区别?
浏览器根据文档开头的 DOCTYPE 决定用哪种渲染模式。写 <!doctype html> 进入无怪异模式,也就是标准模式;缺少 DOCTYPE 会进入怪异模式,模拟老浏览器的布局行为;部分旧 DOCTYPE 会进入有限怪异模式。可以用 document.compatMode 查看当前模式。
简答
HTML 文件第一行的
<!doctype html>是写给浏览器的开关。有了它,浏览器按现代 HTML 和 CSS 规范来排版;没有它,浏览器会进入怪异模式,模仿上世纪 Navigator 4 和 IE5 的布局方式。为什么要有两种模式?在 Web 标准普及之前,很多网站是按老浏览器的非标准行为写的。浏览器开始遵循标准时,为了不让这些老页面错乱,就用 DOCTYPE 来区分:老页面一般没写或写的是旧 DOCTYPE,按旧规则渲染;新页面写了标准 DOCTYPE,按标准渲染。
现在规范里有三种模式:无怪异模式(以前叫标准模式)、有限怪异模式(以前叫“近乎标准模式”,只保留极少数怪异行为)和怪异模式。MDN 说明
<!doctype html>唯一的作用就是开启无怪异模式,所有现代浏览器都认它,没有理由写更复杂的 DOCTYPE。要注意 DOCTYPE 必须放在文档最前面。漏写以后,页面可能出现行高、盒子高度等方面的奇怪差异,用
document.compatMode就能检查:'CSS1Compat'是无怪异或有限怪异模式,'BackCompat'是怪异模式。
浏览器怎样决定用哪种模式
HTML 解析规范里有一张详细的表。遇到的 DOCTYPE 名字不是 html、带有一批旧的公共标识符,或者根本没有 DOCTYPE,文档就进入怪异模式。公共标识符以 XHTML 1.0 Transitional、Frameset 开头的,以及带系统标识符的 HTML 4.01 Transitional、Frameset,进入有限怪异模式。其他情况,包括 <!doctype html>,都是无怪异模式。
WHATWG HTML 规范对 DOCTYPE 的解释是,它是因为历史原因才必须写的;省略时浏览器倾向于使用一种和部分规范不兼容的渲染模式。以 application/xhtml+xml 类型返回的 XHTML 文档例外,MDN 说明它们总是使用无怪异模式,不需要 DOCTYPE。
怪异模式到底怪在哪
这些行为差异写在 WHATWG 的 Quirks Mode 规范里。下面是用 headless Chrome 实测的两个例子,同一段 HTML 只改 DOCTYPE:
<div style="font-size: 16px">
<img style="width: 10px; height: 10px" src="dot.gif" />
</div>
<p style="color: ff0000">没有 # 的颜色</p>
写 <!doctype html> 时,div 的高度是 24px,因为图片按基线对齐,下方留出了行内文字需要的空间,这就是常说的“图片下面有一条缝”。删掉 DOCTYPE 进入怪异模式后,div 高度变成 10px,正好贴着图片。规范里叫行高计算怪异行为:只包含图片这类内容的行,不按 line-height 留出最小高度。用带系统标识符的 HTML 4.01 Transitional DOCTYPE 进入有限怪异模式时,高度也是 10px,因为这一条在有限怪异模式下同样生效,compatMode 却显示 'CSS1Compat'。
那个缺 # 的颜色 ff0000,标准模式下是无效值,文字保持黑色;怪异模式下按规范里的“无井号十六进制颜色怪异行为”被当作红色。同一次实测里还能看到,怪异模式下 body 会被撑满整个窗口高度,对应规范里的“body 填满 html 元素”。
所以漏写 DOCTYPE 引起的往往是这类细小的布局差别,不容易一眼看出原因。
常见追问
DOCTYPE 前面有注释或空行会怎样?
只有空白和注释在前面,解析器还能识别后面的 DOCTYPE。但 MDN 的建议是把 DOCTYPE 放在文档最开头、任何其他内容之前。如果前面出现了别的标签或文字,解析器就把它当成没有 DOCTYPE 处理,进入怪异模式。
怪异模式下盒模型也不一样吗?
规范里确实有一条:怪异模式下,表格单元格计算高度时按
border-box处理。但不是所有元素的盒模型都变了。想主动使用border-box,在标准模式下写box-sizing: border-box即可,见《标准盒模型和 border-box 有什么区别?》。