pseudo-elements 与 :not pseudo-class 的互动

Interaction of pseudo-elements with :not pseudo-class

简短版本:

使用Chrome,我注意到选择器

#main-content p:first-of-type::first-letter:not(.subhead) { ... }

似乎无法应用 first-letter 样式,无论段落的 class 是什么,但是如果我将 :not pseudo-class 放在前面,如

#main-content p:first-of-type:not(.subhead)::first-letter { ... }
#main-content p:not(.subhead):first-of-type::first-letter { ... }

然后它按我预期的那样工作。这是 Chrome 中的一个问题,还是 CSS 选择器的某些方面解释了这一点,我就是不明白?

(此外,如果这不仅仅是 Chrome 中的问题,有人可以为这个问题建议一个更好的标题吗?)


长版:

简短的版本似乎是一个很好的 self-contained 问题,但有一些更复杂的背景信息可能有其自身有趣的后果。 (这可能需要单独的问题,或者是另一个错误。非常感谢帮助???)

最初我试图将 drop-caps 应用于 div 中的第一段以及紧跟水平线的任何后续段落,除非它们是副标题的一部分。这是页面结构的 highly-abbreviated 模拟:

<div id="main-content">
<section class="panel">
  <header>
    <h1>Welcome Friend!</h1>
    <p class="subhead">This is a subheader! (0)</p>
  </header>
  <div class="customhr"></div> <!-- consciously NOT an hr tag -->
  <p>Here's a paragraph (1)</p>
  <hr>
  <p>First paragraph of a new content section (2)</p>
  <p>And another paragraph. (3)</p>
</section>
</div>

和 extremely-abbreviated CSS:

#main-content p:first-of-type::first-letter,
#main-content hr + p::first-letter {
  /* Drop-cap styles */
}
.subhead::before {
  /* Indent sub-headings with a cute fleuron */
  content: "[=15=]a0[=15=]a067[=15=]a0";
}

在 Firefox 中测试时,这导致第 (1) 和 (2) 段具有 drop-caps,这正是我想要的。然而,在 Chrome 中,第 (0) 段的 ::before 规则中的 fleuron 也应用了 drop-cap 样式。我相当有信心 Firefox 在这里出错,因为 :first-letter 应该匹配来自 ::before pseudo-element 的文本,如果它存在,而是 ::before 导致 :first-letter 不匹配任何东西。

在尝试为 Chrome 修复它时,我将 :not pseudo-class 添加到第一个选择器的末尾(请参阅简短版本中的第一个 CSS 规则)。在 Firefox 中,具有讽刺意味的是,这会像以前一样产生预期的效果,但在 Chrome、 这现在导致第 (1) 段不再应用 drop-cap 样式.那个,我没有解释,但我确定它与 .subhead 元素无关; Chrome 显然只是从不应用该规则,并且遵循水平规则的段落是唯一具有样式的段落。但是如果我在规则的前面移动 :not pseudo-class ,就像我在简短版本中给出的两个备选方案一样,它再次按预期工作。

我觉得好像我同时偶然发现了 Firefox 和 Chrome 中的两个 不同 错误,但是使用 pseudo-classes 和 pseudo-elements 对我来说有点神秘,我对他们并不完全有信心。所以我很好奇 a) 是否有什么 in-spec 可以解释这两个浏览器中的 CSS 行为是正确的,并且 b) 如果不是,这些是否是已经在某处记录的具有一致行为的已知错误。 [并且 c) 如果没有,请告诉我您是否打算报告所述错误,以免我不小心重复提交。]

::first-letter::after/::before 确实在 Firefox 中交互,但仅当第一个字符是字母、数字或某些标点符号时。 ::first-letter 似乎忽略了其他符号(如花序),无论是否存在 ::after/::before (JSFiddle)。

Chrome 是 IMO 关于 :not() 和伪元素之间关系的权利。 The documentation 表示伪元素必须始终出现在末尾(这就是为什么短版本的第一个选择器不起作用的原因):

Only one pseudo-element may appear per selector, and if present it must appear after the sequence of simple selectors that represents the subjects of the selector