CSS 标识符可以以两个连字符开头吗?

Can CSS identifiers begin with two hyphens?

CSS 2.1定义identifiers

In CSS, identifiers can contain only the characters [a-zA-Z0-9] and ISO 10646 characters U+00A0 and higher, plus the hyphen (-) and the underscore (_); they cannot start with a digit, two hyphens, or a hyphen followed by a digit. Identifiers can also contain escaped characters and any ISO 10646 character as a numeric code.

因此,-- 应该是一个无效标识符,因此 #-- 不应该 select 带有 id="--" 的元素:

body { color: black }
#-- { color: red }
<p id="--">I should be black.</p>

attribute selectors,

Attribute values must be identifiers or strings.

但是 -- 似乎可以用作属性值的标识符,至少在 Firefox 上是这样:

body { color: black }
[id=--] { color: red }
<p id="--">I am red on Firefox.</p>

此外,CSS.escape 已修改为允许 --:

Minor changes has been made in Firefox 32, to match the spec and the evolution of the CSS syntax. The identifier now can begin with -- and the second dash must not be escaped.

根据 Wayback Machine,更改发生在 2014 年 4 月 19 日至 30 日之间:

那么,是否有一些新的 CSS3 模块更改了标识符的定义,以便它们有时可以以 -- 开头,或者这里到底发生了什么?

我不确定对此是否有确定的答案,但就其价值而言,双连字符出现在定义自定义属性的 CSS Variables module 中。这是一个示例(目前仅在 Firefox 中有效,这可能是它在 CSS.escape() 中有效的原因):

:root { --color: red; }
p { color: var(--color); }
<p>I am red on Firefox.</p>

CanIUse.com for current status of browser support of this feature: CSS Variables (Custom Properties)

虽然 css-syntax-3 对标识符的定义似乎与 CSS2.1 的定义一致,但它确实对 css 变量本身进行了多次引用。然而,None 这些参考文献似乎解决了自定义 属性 名称使用的 -- 前缀。

css-变量本身says:

A custom property is any property whose name starts with two dashes (U+002D HYPHEN-MINUS), like --foo. The <custom-property-name> production corresponds to this: it’s defined as any valid identifier that starts with two dashes.

最后一条语句特别有趣,因为唯一不与 CSS2.1 和 css-syntax-3 中给出的定义冲突的解释方式是含糊不清: "identifier that starts with two dashes" 可以表示两个破折号不是标识符的一部分,即:

<custom-property-name> = '-' '-' <ident>

或者它们 ,这意味着自定义属性不受标识符的一般定义限制。 <custom-property-name> 产生式的语法无处可寻,在 css-syntax、css-variables 和 CSSOM 中都找不到,这无济于事;该平淡无奇的陈述是唯一可用的定义。

当然,其中的 none 解释了为什么 #-- 被 Chrome 识别为有效,特别是因为 Chrome 没有自定义属性的有效实现.

标准

实际上,CSS 语法模块的更改现在允许标识符以两个连字符开头:

4.3.9. Check if three code points would start an identifier

Look at the first code point:

  • U+002D HYPHEN-MINUS

    If the second code point is a name-start code point or a U+002D HYPHEN-MINUS, or the second and third code points are a valid escape, return true. Otherwise, return false.

此更改出现在 21 Mar 2014 Editor's Draft (changelog), and is still not present in the current Candidate Recomendation, which is the 20 Feb 2014 CR

更改中也有描述:

11.1. Changes from the 20 February 2014 Candidate Recommendation

  • Change the definition of ident-like tokens to allow "--" to start an ident.

原因

www-style, the ...let's change the syntax thread proposed to change the syntax of CSS Variables中:

  1. Tab Atkins Jr. proposed 将自定义属性的语法更改为 "any ident starting with/containing an underscore"。
  2. Chris Eppstein disagreed 因为 _property 是一个常见的 IE6 hack。
  3. 布赖恩·卡德尔 proposed --.
  4. 扎克温伯格 warned:

    Unfortunately, "--" would require a change to Syntax. IDENT isn't allowed to start with two dashes in a row.

  5. 对于应该做什么进行了长时间的讨论。

  6. Tab Atkins Jr. informed 他们决定使用 -- 前缀来表示自定义属性和其他自定义内容。

所以第二天他 commited 将 CSS 语法更改为 github(他是规范的编辑)。

实施

Firefox

Firefox 允许标识符以 -- 开头,因为 Nightly 31 2014-04-03 (pushlog). The behavior was changed in bug 985838:

Bug 985838 - change var- prefix of CSS Variables to --

Recently decided changes to the CSS Variables spec:

  • the prefix of the custom property change from var- to --
  • inside the var() you use the full custom property name (i.e. with the -- prefix)
  • a custom property consisting only of the prefix, --, is allowed
  • idents in the CSS parser now allow things like -- and --0

变化发生在 Firefox 31.0。从那时起,[id=--] 有效。

然而,即使在 latest Nightly 41 上,#-- 仍然不起作用。 为了解决这个问题,我提交了 bug 1175192

Chrome

内置 Chromium a new CSS parser

We now allow idents to start with --

已在 this commit, which was part of this commitlist, which was rolled in this commit. So it was finally implemented in build 44.0.2370.0 325166 (pushlog since 325152) 发货。

从那时起,Chromium 允许 [id=--]#--