0

在 CSS 中,通常它可以提高代码的可读性,而不是换行长行,而是确保所有行水平地适合代码编辑器的视口。

但是空白在 CSS 中非常重要,通常使这个目标具有挑战性。

因此,有时在长 CSS 选择器(在 CSS 规则集中)中嵌入注释是一个合理的选择。

我发现选择器喜欢:

div./*  
 */class

工作可靠,但选择器如:

div/*  
 */.class

支持较少。至少,在将 CSS Lint 与这个一起使用时,我在 Stylish 中遇到了错误。

这些中的任何一个(或两者)在技术上是否有效,如果是,那么在 RFC 中的哪个位置表明了这一点?

4

1 回答 1

3

在我回答你的问题之前,我想向你保证,空白在 CSS 选择器中并不像你想象的那么严重,而且在大多数情况下它实际上是微不足道的。它存在的地方很少,您在日常使用中只会遇到其中一个:后代组合器。即使这样,您仍然可以使用换行符代替空格,并且它仍将被解析为后代组合器。我能想到的只有一种情况,那就是复合选择器中的标识符(类、ID、属性等)过长,而您想分解复合选择器。不过,这可能是您无法控制的问题的迹象,所以我不会判断。现在让我们来回答你的问题。

这些特定示例未记录在规范中。预先回答您的问题:它们都是有效的。要了解原因,您需要了解标记化在 CSS 中的工作原理,这在名为css-syntax的规范中有所介绍。值得庆幸的是,CSS 与许多其他语言的注释具有开始和结束分隔符的一个重要共同点是,如果注释干净地位于两个不同的标记之间并且两者都没有被分解,那么这两个标记将解析为完全相同如果没有评论。

但是 CSS 是如何标记化的可能有点令人惊讶。有人可能会假设一个类选择器,例如,.class将被视为基于Selectors 语法的单个标记,因此其中任何地方的注释都会破坏它并导致解析错误:

<类选择器> = '.' <身份令牌>

但是,<class-selector>是一个产生式,它由两个标记组成:被认为是 a 的点<delim-token>,后跟一个<ident-token>。由于点作为与将形成类名的 ident 分开的标记存在,因此注释可能在两个标记 ( ./**/class) 之间干净地存在,同时仍允许将其解析为有效的类选择器。

这适用于类选择器、伪类 ( :nth-child()) 和伪元素 ( ::first-letter)。但是它不适用于 ID 选择器,因为 ID 选择器实际上是一个单一的<hash-token>(考虑十六进制颜色值),注释不能出现在 a (because Reason之前,也不能出现在 ident 中的连字符旁边,因为它是 ident 的一部分。

话虽如此,如果生成的两个标记仍然可以解析,则位于两个字符之间的注释不会立即导致解析错误。但上下文很重要。这是一个例子:

.cla/**/ss

这被解析为以下标记:

  1. <delim-token> '.'
  2. <ident-token> 'cla'
  3. <comment-token>(空的)
  4. <ident-token> 'ss'

这本身并不是一个错误,因为如果我们暂时忘记点,那么我们实际上只有两个标识,它们之间有一个注释,这样的情况是有效的 CSS,你可能有两个或多个标识,否则用空格,就像border: thin/**/dashed等价于border: thin dashed.

但这在 Selectors 中会出现错误,因为Selectors 语法不允许在该上下文中使用两个连续的标识(允许使用的位置数量有限,例如带有i/s标志的不带引号的属性选择器)。

至于div/**/.class,因为divand.class是两个不同的产生式(a<type-selector>后跟 a <class-selector>),它们之间干净的注释不会对解析产生任何影响,所以它仍然会被解析为没有后代组合器的复合选择器。

我所知道的唯一一个无法解析带有注释的选择器的浏览器是 IE8 和更早版本。多年来,这一事实已被利用来产生可靠的选择器黑客。如果你真的必须使用注释来隐藏换行符,否则会破坏你的选择器(因为你已经用完了可以替换常规换行符的地方),我建议使用它们来分隔整个简单的选择器而不是名称中的分隔符因为这样更具可读性。尽管如此,Selectors 4 级规范还是提供了一个列表,其中列出了在选择器中不允许使用空格的位置,因此您可以用 CSS Lint 显然无法解释的方式替换注释:

禁止使用空格:

  • 在 a 的任何顶级组件<compound-selector>之间(即,在<type-selector>and<subclass-selector>之间,或在<subclass-selector>and之间<pseudo-element-selector>,等等)。
  • 在 a<type-selector>或 a 的任何组件之间<class-selector>
  • a or a的 ':' 之间,或 ':' 和<ident-token>or之间。<function-token><pseudo-element-selector><pseudo-class-selector>
  • 在 a 的任何组件之间<wq-name>
  • 的组件之间<attr-matcher>
  • 在 a 的组件之间<combinator>

请注意,属性选择器的大多数部分都允许使用空格(因此换行符),因此不需要使用注释。另请注意,此列表的一个例外是<attr-matcher>,它似乎是一个标记而不是两个<delim-token>s。我在任何地方都找不到这个记录。

再说一次,我真的无法想象必须这样做,但是,嘿,至少你学到了一些关于 CSS 标记化的知识,对吧?

于 2020-11-17T11:28:57.247 回答