CSS 选择器中允许的注释语法
Posted
技术标签:
【中文标题】CSS 选择器中允许的注释语法【英文标题】:Allowed syntax of comments within CSS selectors 【发布时间】:2021-02-28 04:57:09 【问题描述】:在 CSS 中,通常它可以提高代码的可读性,而不是换行长行,而是确保所有行水平地适合代码编辑器的视口。
但空白在 CSS 中非常重要,通常使这一目标具有挑战性。
因此,有时在长 CSS 选择器(在 CSS 规则集中)中嵌入注释是一个合理的选择。
我发现选择器如下:
div./*
*/class
工作可靠,但选择器如下:
div/*
*/.class
支持较少。至少,在将 CSS Lint 与这个一起使用时,我在 Stylish 中遇到了错误。
这些中的任何一个(或两个)在技术上是否有效,如果是,那么在 RFC 中的什么地方说明了这一点?
【问题讨论】:
您看到哪些浏览器存在 div/**/.class 问题? @BoltClock 在使用 CSSlint 时会在 Stylish 中产生错误。 如果抱怨的是 CSS Lint,好吧,我不能完全责怪它 - 这是对 cmets 的一种相当非正统的使用,通常用于 IE 选择器黑客而不是自动换行。但至少你似乎有你的理由。 "因此,有时在长 CSS 选择器(在 CSS 规则集中)中嵌入注释是一个合理的选择。" 我不明白你是如何从认为空格很重要的概念(例如“因此”)[它并没有那么重要,真的......当然远非它在Python中的意义],也不是你为什么不只是发表评论在选择器完全上方或选择器开始行下方的新行上,根据您自己的要求,这将为您提供更好的服务。 "确保所有行在代码编辑器的视口内水平放置。" 代码编辑器视口的宽度可以随时更改,具体取决于某人是否使用更大的显示器或有窗口最大化或任意长度。这似乎不是一件让你自己担心的合理事情,因为你永远不会找到适合所有人的解决方案(也许甚至对“大多数”人都没有)。 【参考方案1】:在回答您的问题之前,我想向您保证,空白在 CSS 选择器中的问题并没有您想象的那么严重,而且在大多数情况下它实际上是微不足道的。它存在的地方很少,您在日常使用中只会遇到其中一个:后代组合器。甚至 then 你仍然可以使用换行符代替空格,它仍然会被解析为后代组合符。我只能想到一种情况,那就是复合选择器中的标识符(类、ID、属性等)变得太长,并且您想分解复合选择器。不过,这可能是您无法控制的问题的迹象,所以我不会判断。现在让我们来回答您的问题。
规范中没有记录这些具体示例。预先回答您的问题:它们都是有效的。要了解原因,您需要了解标记化在 CSS 中是如何工作的,这在名为 css-syntax 的规范中有所介绍。值得庆幸的是,CSS 与许多其他语言(其 cmets 具有开始和结束分隔符)的一个关键共同点是,如果注释干净地位于两个不同的标记之间并且两者都没有被分解,那么这两个标记将解析为完全相同如果没有评论。
但是 CSS 是如何标记化的可能有点令人惊讶。有人可能会假设 .class
之类的类选择器将被视为基于 Selectors grammar 的单个标记,因此其中任何位置的注释都会破坏它并导致解析错误:
然而,<class-selector>
是一个产品,它由两个标记组成:被视为<delim-token>
的点,后跟一个<ident-token>
。由于点作为与将形成类名的 ident 分开的标记存在,因此注释可能在两个标记 (./**/class
) 之间干净地存在,同时仍允许将其解析为有效的类选择器。
这适用于类选择器、伪类 (:nth-child()
) 和伪元素 (::first-letter
)。但是它不适用于 ID 选择器,因为 ID 选择器实际上是单个 <hash-token>
(考虑十六进制颜色值),注释不能出现在 (
之前,因为 reasons,也不能出现在连字符旁边ident,因为它是 ident 的一部分。
话虽如此,如果两个字符之间的注释仍然可以解析,则不会立即导致解析错误。但上下文很重要。这是一个例子:
.cla/**/ss
这会被解析为以下标记:
<delim-token> '.'
<ident-token> 'cla'
<comment-token>
(空)
<ident-token> 'ss'
这本身并不是一个错误,因为如果我们暂时忘记点,那么我们实际上只有两个标识,它们之间有一个注释,这样的情况是有效的 CSS 任何你可能有两个或更多标识的地方否则用空格分隔,例如 border: thin/**/dashed
等同于 border: thin dashed
。
但这在选择器中会出现错误,因为 选择器语法 不允许在该上下文中使用两个连续的标识(允许使用的位置数量有限,例如带有 @987654342 的未加引号的属性选择器@/s
标志)。
对于div/**/.class
,由于div
和.class
是两个不同的产生式(<type-selector>
后跟<class-selector>
),因此它们之间的注释干净地位于它们之间不会对解析产生任何影响,所以这仍将被解析为没有后代组合器的复合选择器。
我所知道的唯一在解析带有 cmets 的选择器时遇到问题的浏览器是 IE8 和更早版本。多年来,这一事实已被利用来产生可靠的选择器黑客。如果您真的必须使用 cmets 隐藏换行符,否则会破坏您的选择器(因为您已经用完了可以替换常规换行符的地方),我建议使用它们来分隔整个简单的选择器,而不是名称中的分隔符因为这样有点可读性更高。尽管如此,选择器级别 4 规范 helpfully provides 列出了选择器中不允许使用空格的位置,因此您可以用 CSS Lint 显然无法解释的方式替换注释:
禁止空格:
在<compound-selector>
的任何***组件之间(即在<type-selector>
和<subclass-selector>
之间,或在<subclass-selector>
和<pseudo-element-selector>
之间,等等)。 在<type-selector>
或<class-selector>
的任何组件之间。 在<pseudo-element-selector>
或<pseudo-class-selector>
的“:”之间,或“:”与<ident-token>
或<function-token>
之间。<wq-name>
的任何组件之间。<attr-matcher>
的组件之间。<combinator>
的组件之间。
注意whitespace (and therefore line breaks) is allowed in most parts of an attribute selector,所以不需要使用cmets。另请注意,此列表的一个例外是<attr-matcher>
,它似乎是一个令牌而不是两个<delim-token>
s。我在任何地方都找不到此文档。
再说一次,我真的无法想象必须这样做,但是,嘿,至少你学到了一些关于 CSS 标记化的知识,对吧?
【讨论】:
以上是关于CSS 选择器中允许的注释语法的主要内容,如果未能解决你的问题,请参考以下文章