<div>嵌套在<p>中。

5
在学习Web开发时,我遇到了一个问题。以下是我的代码:
<!DOCTYPE html>
<html>
<head>
    <style type="text/css">
    p
    {
        background: blue;
    }

    .primary
    {
        color: red;
    }
    </style>
</head>
<body>
    <p>
        text1
        <div class="primary">
            text
        </div>
        text2
    </p>
</body>
</html>

由于某种原因,浏览器将<p>转换为<p>text</p>,并将</p>转换为相同的内容。 因此,我实际上在源代码中编写的是<div>嵌套在<p>中,但是我看到的结果却是这样的:

...
<body>
<p>
text1
</p>
<div class="primary">
    text
</div>
text2
<p></p>
</body>
...

我猜这是因为 <p> 可以是空元素(如 <br>),也可以是非空元素(如 <div>)导致的。请给我解释一下问题并提供解决方案。谢谢。

1
当你说“我得到了这个”时,它来自哪里?是你的编辑器重新格式化了它吗?这是你在浏览器中查看源代码时看到的吗?这是你在浏览器中“检查元素”时看到的吗? - Stephen Ostermiller
@Stephen Ostermiller 2. 是的,那是一个错误。我想说的是在浏览器中查看源代码。 - Serid
2个回答

8
<div>标签和<p>一样,是一个块级元素,这意味着它被设计成包含自己的块,并在其周围具有换行符。尝试将<div>嵌套在<p>中不太可能实现你想要的效果,因为这没有多大意义。一个<p>代表一个段落,不应该包含块级元素。这个问题可能与以下内容相关:https://dev59.com/mm855IYBdhLWcg3whExL。建议使用<span>替代<div>,因为<span>是一个内联元素,被设计成显示在段落内。如果确实需要多个块级元素,请考虑完全不使用<p>或将它们作为最内层块级元素而不是外部元素。

3
起初,有标准通用标记语言(SGML)。SGML定义了一些语法方面的标点和标记,但每个用户应用程序都定义了语法的部分,例如标记名称、属性、嵌套等。
几十年后,SGML简化为创建XML标准。今天许多应用特定数据格式使用XML的方式类似于过去使用SGML的方式。SGML和XML本质上是元语言 - 它们是许多应用特定语言的语法模板。
HTML最初被设计为SGML的一个应用程序,因此了解HTML的历史需要了解一些SGML规则。SGML旨在可以在文本编辑器中进行编辑,因此它包含了许多功能,以减少代码量,使人类编写和阅读更加方便。这里只举几个例子:
一些元素,如<br>是自闭合的,因此不需要对应的</br>结束标签。 一些元素,如<tbody>会被隐式插入,例如<table><tr><td></td></tr></table>将变成<table><tbody><tr><td></td></tr></tbody></table>。 一些元素,如<p>不能嵌套在彼此之中,因此开始一个新的段落会终止旧的段落:<p><p>将变成<p></p><p></p>
这些元素/标签级别的语法特性是通过SGML声明和文档类型定义(DTD)启用/禁用的。HTML版本4.01之前肯定有一个DTD,它被认为是解析器应该如何解释标记代码的真实来源。DTD还可以告诉我们一些东西,比如(不是全面的列表):
- 每个元素允许具有哪些属性。 - 属性是可选的、必需的还是具有默认值。 - PCDATA和CDATA之间的区别,影响字符如何被转义。 - 确切地说,什么元素可以嵌套在什么元素中。
至少从历史上看,DTD是我们可以找到答案的地方,例如HTML 4.01严格版
<!ELEMENT P - O (%inline;)*            -- paragraph -->

<!ENTITY % inline "#PCDATA | %fontstyle; | %phrase; | %special; | %formctrl;">

<!ENTITY % fontstyle
 "TT | I | B | BIG | SMALL">

<!ENTITY % phrase "EM | STRONG | DFN | CODE |
                   SAMP | KBD | VAR | CITE | ABBR | ACRONYM" >

<!ENTITY % special
   "A | IMG | OBJECT | BR | SCRIPT | MAP | Q | SUB | SUP | SPAN | BDO">

<!ENTITY % formctrl "INPUT | SELECT | TEXTAREA | LABEL | BUTTON">

以上代码表示一个

元素只能包含内联内容,进一步定义为任何#PCDATA%fontstyle%phrase%special%formctrl。后4个的定义是一组31个元素,如<tt><strong><img><textarea>等。请注意,这些所谓的内联元素不包括块元素,如<div><ul>等,因此换句话说,<p>不能包含<div>元素。

我不知道 SGML 解析器在每种情况下的行为细节,但看起来当一个元素不允许包含另一个元素时,第一个元素会被终止,然后第二个元素开始。这就解释了为什么 <p><div></div></p> 变成了 <p></p><div></div><p></p>
快进到 HTML5,它不再基于 SGML。虽然 HTML5 是一种独特的语法标准,但它旨在向后兼容 HTML 4。HTML5 复制了正确的 HTML 4 代码的语义,并且还规定了一种统一的方式来解析错误的标记代码("标记汤"),以便所有浏览器都表现相同。因此,<p><div></div></p> 的解释仍然与 SGML 时代没有变化。
对于特别的 `

` 标签,规则在这里 here 有很清楚的解释:

如果一个 `

` 元素紧接着跟着一个 `

`、`
`、`

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