CSS特异性不遵循公式

CSS Specificity is not following the formula

我有以下代码

<style type="text/css">
    .el3 { font-family: Arial, sans-serif; }
    .el1, .el3 { font-family: Tahoma, sans-serif; }
    .el1, .el2, .el3 { font: Helvetica; }
</style>

<div class="el3">Text</div>

当我加载浏览器并使用 class el3 检查元素时,我发现字体系列是 Tahoma, sans-serif.

我知道我没有将 classes .el1.el2 添加到我的 HTML,但我仍然希望结果是 Helvetica.当我检查该元素时,该裁定被划掉了。

字体应该是 Helvetica 有两个原因。

特异性公式如下

  1. 如果样式是内联的则加 1 分
  2. 为查询中的每个 id 选择器加 1 分
  3. 为每个 class、属性或伪 class 选择器加 1 分
  4. 每个元素或伪元素加1分

分数通常以括号表示法衡量。在我的例子中,三个规则将被赋予这三个特异性分数

.el1                    => {0,0,1,0}
.el1,.el2               => {0,0,2,0}
.el1, .el2, .el3        => {0,0,3,0}

是否定义了 .el1.el2 应该没有区别。 3 class 选择器的优先级应该高于 2 class 选择器。

第二个原因是,即使它们具有相同的优先级,决胜局也会转到规则 3,因为它出现在最后。

这也不可能是因为前两条规则我使用了 font-family 属性 而最后一条我使用了 font.

根据优先规则,字体显然应该是Helvetica

问题不在于特异性,而在于有效性。使用给定的规则:

.el3 { font-family: Arial, sans-serif; }
.el1, .el3 { font-family: Tahoma, sans-serif; }
.el1, .el2, .el3 { font: Helvetica; }

最后一个未应用,因为它被视为无效。您可以通过测试来确认:

.el3 { font: Arial, sans-serif; }
.el1, .el3 { font: Tahoma, sans-serif; }
.el1, .el2, .el3 { font: Helvetica; }

其中 none 的字体系列被应用。这似乎与 shorthand 属性(如 font)的验证方式有关。如果我将第二组测试规则更改为:

.el3 { font: 1em Arial, sans-serif; }
.el1, .el3 { font: 1em Tahoma, sans-serif; }
.el1, .el2, .el3 { font: 1em Helvetica; }

然后应用最后一条规则。这似乎与 CSS spec on shorthand properties 相反,它实际上警告说使用 shorthand 而不指定所有属性将导致 属性 被视为设置为 属性 的初始值:

When values are omitted from a shorthand form, unless otherwise defined, each “missing” sub-property is assigned its initial value.

This means that a shorthand property declaration always sets all of its sub-properties, even those that are not explicitly set. Carelessly used, this might result in inadvertently resetting some sub-properties. Carefully used, a shorthand can guarantee a “blank slate” by resetting sub-properties inadvertently cascaded from other sources. For example, writing background: green rather than background-color: green ensures that the background color overrides any earlier declarations that might have set the background to an image with background-image.

但我认为由于根本没有应用该规则,客户端(浏览器)反而只设置了一个 shorthand 属性 来处理 属性完全无效。

进一步的发现:

我不确定他们的来源是什么,但是 MDN doc on the font property 确实明确提到了这个问题:

Note: There are a few caveats when using the CSS font shorthand. If these conditions are not met, the property is invalid and is entirely ignored.

  • Except when using a keyword, it is mandatory to define the value of both the font-size and the font-family properties.
  • Not all values of font-variant are allowed. Only the values defined in CSS 2.1 are allowed, that is normal and small-caps.
  • Though not directly settable by font, the values of font-stretch, font-size-adjust and font-kerning are also reset to their initial values.
  • The order of the values is not completely free: font-style, font-variant and font-weight must be defined, if any, before the font-size value. The line-height value must be defined immediately after the font-size, preceded by a mandatory /. Finally the font-family is mandatory and must be the last value defined (inherit value does not work).

来自规范的来源:

如果您查看 font property specification,它具有以下内容:

Value: [ [ <'font-style'> || <'font-variant'> || <'font-weight'> ]? <'font-size'> [ / <'line-height'> ]? <'font-family'> ] | caption | icon | menu | message-box | small-caption | status-bar | inherit

对于任何可以视读 EBNF(不是我)的人来说,这意味着 shorthand 需要设置(关键字)或(字体大小和字体系列)才能认为有效。上面的语法看起来有点像:

[ 
    [ <'font-style'> || <'font-variant'> || <'font-weight'> ] 
    ? 
    <'font-size'> [ / <'line-height'> ] 
    ? 
    <'font-family'> 
] 
| caption | icon | menu | message-box | small-caption | status-bar | inherit