为什么HTML5中浏览器仍然会注入<tbody>标签?

34

HTML5 doctype example.

<table>里面的元素,无论是IE9还是Chrome14都将TBODY作为该元素的tagName

关于<table>的HTML5规范明确说明:

接下来要么是零个或多个元素,要么是一个或多个元素

此外,关于<tr>的HTML5规范明确说明:

作为表格元素(<table>)的子元素,必须在任何标题、列组(colgroup)和表头(thead)元素之后,但只有在没有是表格元素(<table>)的子元素。

为什么浏览器会破坏我的DOM并注入一个<tbody>当:

  • 我没有请求它
  • 没有<tbody>也是完全有效的

回答“向后兼容性”毫无意义,因为我明确选择了HTML5 doctype。


1
@Raynos 我的意思是那些遗留浏览器代码。构成我们浏览器DOM解析算法的代码。 - jimbo
@JasonMcCreary 我正在使用 Chrome 检查器。我会更具体一些。 - Raynos
可能它们(Chrome、其他浏览器)本身在打印模式下依赖于它来进行呈现...我同意这很愚蠢。 - sg3s
@sg3s,问题在于这些浏览器不符合HTML5标准。如果是这种情况,那么这就是一个bug,并且将被提出来。 - Raynos
2
它怎么不符合HTML 5标准?正如您所指出的,TBODY并非必需,但它是完全有效的。 - kindall
显示剩余8条评论
6个回答

41
“向后兼容”的答案完全没有意义,因为我明确地选择了HTML5 doctype。然而,浏览器不区分HTML的版本。具有HTML5 doctype和HTML4 doctype的HTML文档(除了在FPI中没有URL的HTML4 transitional doctype的小例外)以相同的方式解析和呈现。我将引用HTML5解析器描述的相关部分
“8.2.5.4.9 在表格中插入模式” ... “一个标签名为‘td’、‘th’或‘tr’的开始标签” 假装看到了一个标签名为“tbody”的开始标记,然后重新处理当前标记。

你提到的HTML5解析器非常正确!我稍微详细地写了一下这个问题:浏览器总是假定 TBODY - Alan H.

19

你完全忽略了HTML5规范中树是如何构建的部分。

规范允许你编写一个没有tbody元素的table,因为它是隐含的。就像如果你跳过htmlheadbody的开头或结尾标签,你的页面仍然可以正确地呈现。

我假设你希望DOM包含一个body来显示你的内容,如果由于任何原因遗漏了它。同样适用于tbody。它被添加进去,是因为它明确地假定你忘记了自己加上它。

表格解析规则

开始标记的标记名称为"td"、"th"、"tr"之一

假装看到了一个标记名称为"tbody"的开始标记标记,然后重新处理当前标记。


7

根据我的经验,浏览器不会区分HTML5和HTML4文档。它们对两者的行为相同。在浏览器中,<!doctype html>不会触发任何特殊行为。

<!doctype html>不是专门为"HTML5文档"保留 - 它只是最简单的可触发标准模式的文档类型声明。


4
@Raynos,我不使用“HTML5文档”这个名称。网页是HTML文档。一些网页使用在HTML5中首次定义的功能,而其他一些则没有。但它们都是HTML文档。我的回应可能是:给HTML文档命名为HTML5文档有什么意义呢? - Šime Vidas
但是我们可以明确地将文档类型定义为HTML3、HTML4或current。那么这样做有什么意义呢? - Raynos
据我所知,定义doctype的唯一原因是触发标准模式。除此之外,doctype没有任何作用。再次强调,据我所知。 - Šime Vidas
3
对于浏览器来说,那就是唯一的原因。验证器则有所不同。 - Alohci

5
大部分这种情况是由于HTML5将HTML 4的继承者和XHTML 1.x合并为一个规范而产生的。
当XHTML 1.0被引入并且浏览器开始尝试使用XML解析器时,出现了一个问题。作者习惯于编写没有tbody标签的表格(如:table)。由于XML解析器不允许像HTML解析器那样推断标签,帮助作者过渡到XHTML(当时似乎是个好主意)的最佳方法是通过在DOM中允许tr直接成为table的子元素来正确呈现表格。(DOM尽可能相同,无论它是源自HTML解析还是XML解析。)因此,浏览器实现了对此的支持。
现在,HTML5内容模型在HTML和XHTML序列化之间共享,因此必须允许两种排列方式,即有或没有tbody。
另一方面,在“HTML语法”部分(不适用于XML解析器),它明确表示HTML解析器将推断tbody标签。
<table><tr><td>my text</td></tr></table>text/html形式提供时,DOM中创建的表格结构将具有tr作为tbody的直接子元素,tbody作为table的直接子元素。HTML5内容模型表示这是可以的。
<table><tr><td>my text</td></tr></table>application/xhtml+xml形式提供时,DOM中创建的表格结构将具有tr作为table的直接子元素。HTML5内容模型表示这也是可以的。
也可以通过脚本将tr创建为table的直接子元素。出于同样的原因,浏览器将把它视为大多数人所期望的表格行。

为什么“text/html”会注入“<tbody>”标签?有没有很好的理由? - Raynos
@Raynos - 就像其他人指出的那样,这是为了向后兼容。许多脚本和CSS选择器假定浏览器将继续执行它们一直在执行的操作,并且tbody元素将存在。 - Alohci
但是那些相同的脚本和CSS选择器在“application/xhtml+xml”上不会出现问题吗? - Raynos
3
是的,许多库代码通常会这样做。但XHTML与之不同,大多数将其作为XML服务的作者使用不同的脚本和CSS来避免这些问题。 - Alohci

3

由于“历史原因”(即向后兼容性,这对HTML非常重要),某些元素具有额外的限制,甚至超出了它们的内容模型所给出的限制。

表格元素 table 不应包含行元素 tr,即使根据本规范中描述的内容模型,这些元素在技术上允许位于 table 元素内部。(如果在标记中将 tr 元素放入 table 中,则实际上会暗示它之前有一个 tbody 开始标签。)

请注意,此引用 来自“HTML语法”部分。此部分仅适用于文档、作者工具和标记生成器,而明确不适用于一致性检查器(需要使用HTML解析算法)。

因此:规范说明使用 tr 标签在 tbody 之外是允许的,根据内容模型和解析规范,但是生成HTML的任何工具(包括您)都应该使用 tbody


这直接与“作为表元素的子元素”相冲突。为什么WHATWG规范覆盖了HTML5规范所说的呢?为什么会存在矛盾? - Raynos
1
你能解释一下“内容模型”和DOM有什么不同吗?(通过编辑答案) - Raynos

1

向后兼容性不仅仅限于文档类型声明,脚本可能依赖存在 tbody 元素。


3
请勿包含与HTML5不兼容的脚本。如果您选择使用HTML5,请勿使用错误的代码。 - Raynos
@Raynos,虽然我同意,但浏览器是为那些在HTML中做坏事的人设计的。 - user142019

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接