为啥 # 选择器的特异性比任何东西都低?

Posted

技术标签:

【中文标题】为啥 # 选择器的特异性比任何东西都低?【英文标题】:Why is the # selector of lesser specificity than anything?为什么 # 选择器的特异性比任何东西都低? 【发布时间】:2011-03-19 16:55:16 【问题描述】:

粗体大写锁定 TL;DR:

我知道选择器的特异性是如何确定的,我认为它使用了有缺陷的假设,我可以用有效的集合理论关系来支持我的愤怒,请不要回应解释 W3 计算规则的具体性,请阅读问题强>

当我为一些类似于下面的 html 编写样式时,这困扰了我一段时间:

...
<div id="outer">
    <span id="inner"></span>
    <span></span>
    ...
</div>
...

为什么特异性规则会使选择器“#outer span”比“#inner”更具体? ID 是唯一的,所以当我说“#inner”时,我只能指代一个元素,那么为什么它不那么具体?我了解确定特异性的规则,我只是想知道这是故意的还是偶然的,以及是否有人知道我如何向编写 css 标准的人提出这个问题。

我应该注意,我知道我可以使用#outer #inner 来确保最大的特异性,但这似乎首先违背了 ID 的目的。当我编写模板并且我不确定一个 ID 是否会在另一个 ID 中时,这也是一个有问题的解决方案。我不是在寻找解决方法,只是在寻找理论答案。

我的问题是理论,完全基于集合逻辑。尽管我的想法是,如果您为 n 个可能项目中的 1 个项目定义一个规则,那不是尽可能具体吗?为什么 CSS 选择器的创建者会制定一个可以定义 n 个可能项目中的 m 个项目的规则,其中 m 是 n 的子集作为更具体的规则?

我的想法是,#id 相当于通过名称识别 1 个项目,而 #id elm 将通过名称与项目的关系来识别组。使用命名关系调用命名项不如调用未命名组具体是完全违反直觉的。

【问题讨论】:

你是怎么得出这个假设的? @Felix 这完全违背了我的预期,但这是真的。 jsfiddle.net/DUKkT 【参考方案1】:

因为#outer span 有一个 ID 选择器和一个元素选择器。这个元素选择器使它的重量超过了#inner

前者的意思是“选择在 ID outerany 元素中找到的 any 元素。 后者表示“选择 ID 为 innerany 元素”。它不知道#inner 在您的 HTML 文档中的位置,因此特异性较低。

也许你可以试试#outer #innerspan#inner 试试#outer span#inner

【讨论】:

将相同的原则应用于不同的情况,用户名。如果我说“BoltClock”,我已经通过名称识别了我正在谈论的用户,那么您就不能再更具体地针对哪个用户了。如果我说“BoltClock 的评论者”,我指的是比 ALL USERS 更具体的用户子集,但不一定只有一个,这使得它在集合符号方面不太具体。整个系统使用有缺陷的集合逻辑。 感谢您的解决方法,但作为一个真正固执的人,我必须坚持认为他们识别特异性的系统是错误的,并且拒绝更改。我通常只做#innerrule:rule !important; 事实上,我自己也一直想知道这一点,并且一开始发现它同样违反直觉。但我想每个人都不一样——我一直在平静地适应 CSS 的做法。 质疑权威从来都不是坏事,总得有人考虑网络标准吧?如果没有意义,应该讨论一下。我想也许是这样,所以我问了。 BoltClock,我现在更喜欢以下:#inner[id]【参考方案2】:

如何

W3C rules for calculating specificity:

如果声明来自是“样式”属性而不是 带有选择器的规则,否则为 0 (= a) (在 HTML 中,元素的值 “style”属性是样式表 规则。这些规则没有选择器, 所以 a=1、b=0、c=0 和 d=0。) 统计选择器中 ID 属性的数量 (= b) 计算其他属性和伪类的数量 选择器 (= c) 统计选择器中元素名称和伪元素的数量(= d)

特异性仅基于 选择器的形式。特别是,一个 “[id=p33]”形式的选择器是 算作一个属性选择器(a=0, b=0, c=1, d=0),即使 id 属性被定义为“ID” 源文档的 DTD。

连接四个数字 a-b-c-d (在具有大基数的数字系统中) 给出特异性。 此外,当规则具有相同的特异性时,最后一个获胜。

示例

外跨度:a=0, b=1, c=0, d=1 --> 101

span#inner: a=0, b=1, c=0, d=1 --> 101 div#outer span#inner: a=0, b=2, c=0, d=2 --> 202

尝试重新排列规则 1 和 3:http://jsfiddle.net/Wz96w/

为什么

我的想法是#inner 没有指定唯一元素。虽然每个页面只有 1 个元素,但该 ID 可能是另一个页面上完全不同的元素。

一页:

<div id="outer">
  <div id="inner"> ... </div>
</div>

另一页:

<ul id="outer">
  <li>main1
    <ul id="inner">
      <li>sub1</li>
      <li>sub2</li>
    </ul>
  </li>
  <li>main2</li>
</ul>

虽然,我不会这样编码。我认为它解释了为什么添加元素(ul#outer#outer)值得额外的特异性。

关于后代的观点,我正在为您的标记可视化 DOM。规则#outer span 的路径长度比#inner 的路径长度长。因此,在这种情况下,它指定了一个更具体的子树,因此应该授予它更多的特异性(并且#outer #inner li 应该 [is] 比#inner li 更有价值)。

【讨论】:

复制并粘贴,我很抱歉破坏了你的努力,但问题是为什么事情是这样的,而不是如何服从它们:“再次,我不能强调这一点:我不是在问 #_id_ 选择器如何小于 #_id_ 元素选择器的问题,我是在问为什么会这样。” 我很欣赏这个例子,T,但你自己的句子应该否认这个例子:“虽然,我不会这样编码。”不应该为良好的编码风格编写标准吗?如果我将样式表附加到按名称调用元素并告诉它如何行为的页面上,它不应该遵守任何通用规则吗? 我添加了澄清说明 #inner 不一定只用于一个元素;它可能是其他页面上的不同元素。这就是我为什么 W3C 选择以这种方式计算特异性的假设的一部分。顺便说一句,有趣的问题。 我绝对认为 elm#id 和 #id1 #id2 的排名应该高于 #id,解决您提出的情况。但我不认为#id1 elm 的排名应该高于#id2,而且我认为共享样式表没有必要这样做。【参考方案3】:

我认为“为什么”这个概念更多是一种“代际”或“权威”的观点。如果#Parent(任何一代人)说我所有符合资格“x”的孩子(在你的情况下,span)都将获得“y”(无论css属性)的继承,它不会单身#Child想要什么,如果父母另有说明,需要#Parent的授权才能得到。

在编辑时添加: 内联 style 将是叛逆的孩子,而 !important 将是打击父母。 编辑:我保留这个是为了幽默,但我不认为它反映了这个想法以及我后来在下面的陈述。

在评论中添加了对问题的编辑:鉴于:

#outer span ...
#inner (which is a span element)

然后,为了帮助确保#inner 选择,我建议:

body span#inner (*edit:* just span#inner works *edit:* if defined later)

或者给body一个id和

#bodyId #inner

当然,这些仍然可以被覆盖。涉及的“世代”越多,由于世代共识而改变行为就越困难(如果曾祖父和祖父以及父母都同意,那么孩子很可能不会做自己的事) .

我不得不在以后的编辑中主要重写这部分 鉴于此 HTML:

<div id="grandparent">
  <div id="parent">
    <div id="child"></div>
  </div>
</div>

我之前说过“#parent div#grandparent div 具有更大的权限。两者都具有世代权限,实际上是'平等'的世代权限,但第一个是'更近'的世代”获胜。 错误在于“更接近”世代并不重要,而是最后被授予权力。在同等权力下,自己指定的最后一方获胜。

我相信我仍然可以坚持这样的说法:考虑到这一点,像 #child[id] 这样的选择器(其重要性超过了之前的两个选择器)将其属性视为权限,以获得更大的权限来统治自己所控制的东西。拥有 # 已经赋予了它权限,但如果早一代还带有另一个授予更多权限的选择器,则不足以覆盖早一代的 #。

所以#grandparent div 超过#child 但不是div#child 如果它是最后一个获得权限[添加这个],而不是#child[id] 因为[id] 增加了更大的权限#child 统治自己。如果选择性相同,则最后一个被授予权限的人获胜。

同样,style 属性设置样式属性本身实际上更像是一种至高无上的权力授予来统治自己,假设更多的“!important”不会剥夺它。

作为回答“为什么”的总结性陈述(不符合“集合”理论),我认为这与 准确性 甚至特异性 (尽管这是使用的术语),因为确实有人会期望 #ChildsName 成为这件事的最终唯一发言权,因为没有更具体的内容需要说。然而,虽然文档可能没有这样说明,但“选择性”实际上是基于授予权限而构建的。谁拥有最多的“权利”来统治元素,并给予“平局”,谁是最后一个被授予这些权利的人。

【讨论】:

我认为它更像是使用#Parent 赋予它代际权威,而#Child 单独行动没有父母权威(自我权威)并且只要父母有就可以这样做没有另外说。所以换句话说,你,作者不是父母,#Parent 容器是。如果您,“局外人”想要命令#Child 做什么,如果父母制定了其他可能相矛盾的规则,您必须通过父母权威来执行。 我不认为 css 中的特异性是关于“哪些选择器更准确地识别一组元素”,因为它是 哪些选择器更权威识别一组元素元素。如果您或其他 css 作者表示此属性由#Parent 控制,则您或其他作者有权直接告诉#Child 否则无需 1)通过父母权限的命令链,或 2)更改原始该地区的父母权威。 未检测到磨损性。但是请注意,在您的引文中,1)它没有提到 accuracyauthority (我们对此的想法之间的差异),但是 2)它暗示了 权威 认为它是一棵文档树(很像家谱),最后一句“如果模式中的所有条件都为真”,则匹配也符合权威视图。代际匹配越多,权威越大。 #Child 与 #Parent #Child 没有什么或多或少准确的地方,它们都指的是同一个独特的个体,但在权威上却有天壤之别。 你沉迷于“特定”的诗句“权威”。两者都是同样具体的,并且在某种意义上是“冗余的”,但它是授予 authority 而不是 specificity,因为两者都以元素为目标。有点中世纪,我是“斯科特”,但如果有权威的骑士称我为“斯科特爵士”,那么现在我是#Scott[sir] :-)。 我很高兴“它现在确实有意义”对你来说。我觉得你对 id 是独一无二的这一事实感到困惑,因此当(即使在“现实世界”中)唯一性和做一个人想做的事的权力与彼此没有必要的关系时,它应该对自己拥有绝对的权威。 【参考方案4】:

对我来说,我完全基于意见,这是预期的“自然”行为。

考虑一下:

您知道 CSS 特异性是如何计算的,并且从该公式中我们知道 #outer span#outer 更具体,这对于整个 CSS 正常工作是必要的,而且它是有道理的。 #outer span 也比 #inner 更具体,这在样式表的域内也是合乎逻辑的(#inner 只是一个 ID,#outer span 是一个 ID 加一个元素,所以如果我们要对它们进行排名只是查看样式表,越合格的必须越具体)。

这里发生的情况是,您正在应用 HTML 标记的上下文,并说“嗯,这没有意义”。为了使事情按您期望的方式工作,浏览器必须考虑以下内容:

这个&lt;span id="inner"&gt;&lt;div id="outer"&gt;里面 #outer span#inner 的样式表规则适用 规则#outer span#inner 更具体 但是等等! &lt;span id="inner"&gt;&lt;div id="outer"&gt; 内部,因此忽略基于样式表的计算,并声称 #inner 更具体

最后一步使确定过程完全基于 HTML 的结构,这使得仅根据 CSS 定义特异性是不可能的。我个人认为这会使整个过程更加复杂且难以定义,但您可能不同意。

【讨论】:

您在第一段中的意思是“id”而不是“class”。我不确定如何在 SO 中发送 PM,但我明白。我根本没有在这里应用 HTML,我知道 CSS 在 HTML 中有规则,并且在一个页面中不能多次使用 id,这意味着当我只为 id 编写规则时,我只能谈论 1 个元素.我的问题是为什么我会希望我为那个单独的元素编写的规则被覆盖。 你的整个过程可以通过简单的理解绕过。如果一个 id 被声明了两次,则它不是有效的 HTML,因此任何通过 id 的规则只能谈论 1 个元素。 哎呀,不知道我在想什么。谢谢,我现在更正了。你是对的,但是你会如何根据你可以单独在 CSS 中确定的内容来定义它?没有办法使用#inner 可能比#outer span 更具体的CSS 特异性规则,因为#outer span 必须比#outer 更具体。我们知道,一旦我们到达 HTML,#inner 可能会被认为更具体,但是当我们解析 CSS 时,我看不到了解/定义它的好方法。 我们可以推迟决定,直到我们查看 HTML,但出于实现的原因,这可能不是最佳的。当然,如果#inner 不是#outer 的后代,则规则完全不相关,因此说#inner#outer span 更具体也不一定有意义,因为它们是不相关的。我认为有空间说整个公式是有缺陷的,因为它没有考虑到这些情况,但我确实觉得“为什么”是在可以使用该公式预先确定的情况下确定的。 是的,但你不能说#inner#outer 更具体,所以当使用基于数字的系统时只解析 CSS 我看不出你如何定义#inner#outer span 更具体,因为它是 #outer + span。我的印象是选择基于数字的系统是因为它是确定特异性的最一致的方法,但我可能是错的。当然,如前所述,它缺乏做出此类决定的能力,但实施起来似乎相当简单。

以上是关于为啥 # 选择器的特异性比任何东西都低?的主要内容,如果未能解决你的问题,请参考以下文章

css 权重 特殊性

为啥日期时间选择器的行为?

xamarin 表单 - 与选择器的两种方式绑定 - 为啥我不能从后面的代码更新选择器?

CSS 特异性过滤器

为啥以两种不同方式应用随机森林分类器的特征选择结果不同

计算css文件中选择器的数量