可以重复类型选择器以增加特异性吗?

Can type selectors be repeated to increase specificity?

关于计算 CSS 特异性的 spec 状态:(粗体)

Note: Repeated occurrences of the same simple selector are allowed and do increase specificity.

因此,例如 .class.class {} 的特异性是 .class {} 的两倍 - DEMO

然而,关于术语“简单选择器the spec 有这样的说法:(大胆的我的)

A simple selector is either a type selector or universal selector followed immediately by zero or more attribute selectors, ID selectors, or pseudo-classes, in any order.

因此,由于规范规定允许重复出现相同的 简单选择器 - 这意味着您也可以重复 type selectors

很明显,这样的事情是行不通的:h1h1 { }

所以我尝试了这个:h1[]h1[] {} - 这也不起作用,

所以我想知道是否有办法做到这一点?

可以使用类型选择器增加选择器的特异性,但不是传统的。下面解释了这样做的原因,但对于那些只是在寻找替代方案的人来说,有两个原因。您可以在单个复合选择器中链接 :not() 伪 classes 包含类型选择器:

h1                      {} /* 1 type  -> specificity = 0-0-1 */
h1:not(_)               {} /* 2 types -> specificity = 0-0-2 */
h1:not(_):not(_)        {} /* 3 types -> specificity = 0-0-3 */
h1:not(_):not(_):not(_) {} /* 4 types -> specificity = 0-0-4 */

或者,如果您需要支持不支持 :not() 的旧版浏览器,您可以在复杂的开头添加冗余类型选择器,例如 htmlbody选择器,尽管在这种情况下您的限制要大得多,因为您可能无法考虑所有元素:

h1                {} /* 1 type  -> specificity = 0-0-1 */
body h1           {} /* 2 types -> specificity = 0-0-2 */
html body h1      {} /* 3 types -> specificity = 0-0-3 */
html body tr > td {} /* 4 types -> specificity = 0-0-4, assumes every td is a child of tr */

不用说,这些被认为是特异性黑客;与所有其他 CSS hacks 一样,尽量少用它们。


复合选择器在所有其他简单选择器之前最多只能有一个类型选择器。来自 Selectors 3(称其为简单选择器序列):

A sequence of simple selectors is a chain of simple selectors that are not separated by a combinator. It always begins with a type selector or a universal selector. No other type selector or universal selector is allowed in the sequence.

Selectors 4

A compound selector is a sequence of simple selectors that are not separated by a combinator. If it contains a type selector or universal selector, that selector comes first in the sequence. Only one type selector or universal selector is allowed in the sequence.

只有类型选择器和通用选择器受此规则约束;您可以组合并重复其他简单的选择器以增加特异性。也许规范可以在计算特异性的部分提醒 reader 这一点,但我认为这不是绝对必要的。

此规则的原因从未明确说明,但很容易推断:

  • 请记住,类型选择器只包含一个标识符,例如h1。这不同于其他简单选择器,它们在语法中有自己的区分符号,例如 ID (#)、class (.)、伪 class (:),或属性选择器 ([])。如果没有单独解析它们的方法,您将无法拥有多个连续的类型选择器。

  • 并且即使您可以链式选择器,例如,如果它们之间有另一个简单的选择器,唯一可能的用途是作为specificity hack,如问题中所述,这意味着您只能在所有类型选择器都相同的情况下使用它;没有其他类型选择器的组合可以工作。

    这是因为选择器假定文档语言将每个元素定义为具有一种元素类型。例如,在 HTML 中,h1 始终是 h1;它永远不能是任何其他类型的元素。要求既是 h1 又是 p 的元素的复合选择器永远不会匹配任何东西,出于同样的原因,像 [type=text][type=password] 这样的东西永远不会匹配文档语言中的任何东西不支持重复属性。

然而,考虑到以上几点,仍然可以创建一个包含多个类型选择器的复合选择器来实现特异性——通过使用 :not() 伪 class:

  • :not()伪class的特殊性等于它的参数。伪class本身不算。这个在第一个link中有提到。这意味着 :not(h1) 的特异性等同于 h1 — 一种类型选择器。

  • 由于一个元素只能是一种类型,这意味着 :not() 与任何其他类型选择器都将保证匹配。

  • 由于复合选择器可能包含任意数量的伪classes,您可以根据需要多次重复否定,即使否定都使用相同类型的选择器。

  • 并且由于选择器不关心选择器在任何特定文档语言的上下文中是否有意义,您可以使用保证永远不会匹配符合 HTML 文档,只要它满足类型选择器的选择器语法。类型选择器只包含一个 CSS 标识符,因此 任何 CSS 标识符都是公平的 。包括_.