为什么带有换行符的 PRE 元素不会在输出中产生空行?

Why does a PRE element with newlines do not produce blank lines in the output?

示例 1

pre {
  background: lightblue;
}
<pre>
<code>
foo
</code>
</pre>

空行出现在foo的上方和下方。这是预期的,因为 PRE 元素中有换行符。

示例 2

pre {
  background: lightblue;
}
<pre><code>
foo
</code></pre>

空行出现在 foo 上方,但下方没有。为什么?

示例 3

pre {
  background: lightblue;
}
<pre><code>foo</code></pre>

foo前后不再有空行,因为HTML代码中没有换行符。

示例 4

pre {
  background: lightblue;
}
<pre>
<code>foo</code>
</pre>

<pre>之后和</pre>之前有换行符。所以我期待输出中 foo 前后的空行。为什么这个例子中没有空行?

问题

  1. 为什么示例2中只有一个空行?
  2. 为什么示例4的输出没有空行?

示例 1 与示例 4 有相似之处。我会回到这个...

示例2和3是基本情况。在示例 2 中,忽略 code 标签,您有 pre 开始标签,一个创建空白行的换行符,"foo",一个结束该行的换行符,然后立即 pre 结束标记。请注意,结束标记前的单个 space 足以在 "foo" 行下创建一个空行。

示例 3 根本不包含新行。但是 pre 默认情况下是一个块级元素,所以 "foo" 无论如何都会出现在它自己的一行上。这个不用多说了。

示例 4 类似于示例 2,只是代码标记移动了行。这暴露了 HTML 解析器的一个特殊之处。 The HTML parsing algorithm says:

↪ A start tag whose tag name is one of: "pre", "listing"

If the stack of open elements has a p element in button scope, then close a p element.

Insert an HTML element for the token.

If the next token is a U+000A LINE FEED (LF) character token, then ignore that token and move on to the next one. (Newlines at the start of pre blocks are ignored as an authoring convenience.)

Set the frameset-ok flag to "not ok".

因此,紧跟在 pre 开始标记之后的初始换行符被丢弃在地板上,并且在 "foo" 行之前没有空行。而在示例 2 中,code 开始标记是紧跟在 pre 开始标记之后的标记,导致后面的换行符不会被忽略。

例1同理。 pre 开始标记后的初始新行被忽略,'codestart tag creates a blank line, then the foo line and its new line character, then the new line following the 'code 结束标记后的新行在 "foo" 行下方创建一个空行,并且 pre元素结束。