理解特异性:在不使用 !important 的情况下实现期望的选择器结果

Understanding specificity: achieving desired selector outcomes without using !important

我正在尝试理解 特异性 CSS。

我目前的理解是特异性与继承非常相似,但在某种程度上更具体地定义。

Mozilla Specificity Definition:

Specificity is the means by which browsers decide which CSS property values are the most relevant to an element and, therefore, will be applied. Specificity is based on the matching rules which are composed of CSS selectors of different sorts.

当前任务是:

重构 .active a.copyright 的 CSS 声明,以便删除 !important 规则。

CSS:

.main li a {
  color: #7ab2c1;
}
.active a {
  color: #826c55 !important;
}
.primary p {
  font-size: 12px;
}
.copyright {
  font-size: 10px !important;
}

和相关HTML:

<nav class="main">
  <ul class="group">
    <li class="active"><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>

[...]

<footer class="primary">
      <p><a href="#">Sign up</a> for our newsletter, it's a racket!</p>
      <p class="copyright">Copyright &copy; Sven's Snowshoe Emporium. All Rights Reserved.</p>
</footer>

谁能以帮助我掌握基本概念的方式指导我完成重构过程?

您可以将 .copyright 更改为很多东西,但以下两个对我来说似乎是最合乎逻辑的:

.primary .copyright

p.copyright

特异性应该做什么,是查看您的选择器特异性,并决定是否应遵循该规则。

    媒体查询内部的
  • CSS 比外部的 CSS 更具体
  • ID 比 类
  • 更具体
  • html body section p.special.selected:hoverp
  • 更具体
  • 等等

有一大堆规则可以为您的选择器 'points' 提供每个部分。点数越多,越具体。多练后,想都没想就能写出超裁CSS

A class 的特异性为 10。元素的特异性为 1。

因此,在第一个实例中:

  • .main li a 选择器的特异性为 12。
  • .active a 选择器的特异性为 11

因为它们都针对相同的元素,并且前者具有更高的特异性,所以后者输掉了元素样式的战斗。

二审:

  • .primary p 选择器的特异性为 11。
  • .copyright 选择器的特异性为 10。

同样,因为它们都针对相同的元素,并且前者具有更高的特异性,所以后者输掉了为元素设置样式的战斗。

!important annotation 胜过所有的特异性。因此,应用该元素后,.active a.copyright 重新获取元素。

如果您想删除 !important,这是正确的做法,因为这里没有必要,您可以提高选择器的特异性。

ID 的特异性为 100。因此可以快速将选择器的优先级提高。

这里有一些例子:

.main li a      { color: #7ab2c1; }  /* previous winner; specificity 12 */
.main .active a { color: #ff0000; }  /* added class selector; specificity now 21 */
.primary p      { font-size: 12px; } /* previous winner; specificity 11 */
#copyright      { font-size: 8px;} /* switched to ID selector; specificity now 100 */
<nav class="main">
  <ul class="group">
    <li class="active"><a href="#">Home</a></li>
    <li><a href="#">About</a></li>
    <li><a href="#">Contact</a></li>
  </ul>
</nav>
<footer class="primary">
  <p><a href="#">Sign up</a> for our newsletter, it's a racket!</p>
  <p id="copyright">Copyright &copy; Sven's Snowshoe Emporium.
                    All Rights Reserved.</p>
</footer>

参考文献:

在这个例子中,您试图让正在设置您希望覆盖的属性的选择器不那么具体。这样一来,您就不必费力去覆盖它们。

我们来看看

.main li a {
  color: #7ab2c1;
}
.active a {
  color: #826c55 !important;
}

.main li a 非常具体:它选择在其 class 名称中包含 main 的元素中的 li 中的所有锚标记。你怎么能让它不那么具体呢?根据您的标记,

.main a {
  color: #7ab2c1;
}

不太具体,仍然适用,并且会被您的 .active 选择器覆盖,因为它具有相同的特异性(class + 一个元素)。 nav a 甚至普通的旧 a 也可以用作选择器,具体取决于您希望该规则应用多少(或多少)。

现在,让我们看看页脚。

.primary p {
  font-size: 12px;
}
.copyright {
  font-size: 10px !important;
}

我们怎样才能使第一个选择器不那么具体?改成

怎么样
p {
  font-size: 12px;
}

您的 .copyright 选择器更具体并且会覆盖它(但是,所有 p 元素都将具有 12px 的默认 font-size 并且可能不是你想要什么)。

我们可以将其限制在页脚:

.primary {
  font-size: 12px;
}

这会将 font-size 属性 限制为仅页脚元素,并允许您使用后续规则覆盖它。

一般来说,您正在尝试基于 specificity values 进行重构,以使您想要覆盖的内容具有 可能的最小特异性值 。您可以使用 最通用的选择器来执行此操作,这些选择器将应用您想要的规则,而不将这些规则应用到不应包含它们的元素

基本上使用 html 标签作为选择器会增加少量的特异性,使用 class 会增加中等程度的特异性,使用 ID 会增加大量的特异性,而使用 !important胜过一切

.main li a 选择器使用 1 class + 2 html 标签,而 .active a 只使用 1 class + 1 html 标签。前者比后者更具特异性,但使用 !important 会覆盖它并强制应用后一种样式。

要消除对 !important 的需求,您需要 a) 减少 .main li a 中的特异性量或 b) 增加 .active a 中的特异性量。我会推荐选项 a 并将选择器更改为 .main a。这具有与 .active a 相同的特异性,但由于 CSS 的级联性质,将应用最后出现的样式,不需要 !important

第二个场景的原理相同——.primary p有1个class + 1个html标签,而.copyright只有1个class。在这种情况下,我会选择选项 b 并将选择器更改为 .primary .copyright。 2 classes 比 1 class + 1 html 标签更具体,样式将在不需要 !important.

的情况下应用

最终 CSS:

.main a {
  color: #7ab2c1;
}
.active a {
  color: #826c55;
}
.primary p {
  font-size: 12px;
}
.primary .copyright {
  font-size: 10px;
}