嵌套CSS选择器而不增加特异性

时间:2015-12-23 11:06:04

标签: css css-selectors css-specificity

让我们选择这三个选择器,从最高特异性到最低特异性分类:

.special-section p { }
.weird-font        { }
p                  { }

许多CSS专家建议不要像第一个选择器.special-section p那样嵌套,因为它的特异性足够高,你不能用像.weird-font之类的简单类来覆盖它。我想找到一种方法来像.special-section p一样实现嵌套,但没有增加特异性。像这样:

 .weird-font { }
 .special-section p /* with hack to decrease specificity */ { }
 p { }

用例:

使用简单的选择器(如p)在排版和文档范围内应用默认值是非常安全的。但是,我想更改特定部分的默认值,类似于.special-section p,而不必使用hacks来增加.weird-font等选择器的特异性。我宁愿使用hack来降低.special-section p的特异性,而不是使用hack来提高.weird-font的特异性。有没有办法做到这一点?

4 个答案:

答案 0 :(得分:8)

您无法降低特异性,但可以为异常添加更具体的选择器。

.weird-font, /* Normal weird font */
.special-section p.weird-font /* Override for special section */ 
  { }

但正如你所看到的,它是一个滑动的尺度。那些大师们可能是对的。如果您要删除.special-section p,而是将这些P设为自己的选择器.special-section-para或其他内容,那么您就不会遇到此问题。

但就个人而言,我不介意不得不像上面那样添加一个例外。我认为整个特定的东西就是出于那个目的,如果你需要一个更具体的选择器来设计一些东西,对我来说这似乎是正确的事情。

一个常见的解决方案是使用!important。 !important的问题在于只有一个覆盖级别。如果您创建一个更具体的选择器,您可以使用更加特定的选择器再次覆盖它。在使用!important之后,你就没有选择了。更重要的是,使用!important可能会干扰用户可能具有的特殊样式表以提高可读性。出于这个原因,我从不在这种情况下使用!important

但话说回来,我不认为自己是CSS大师。 ;)

答案 1 :(得分:7)

作为一名CSS大师,我哀叹抛出Selectors必须提供的所有内容只是为了避免特殊性问题。这并不是说我不相信特异性机制是有缺陷的,但肯定没有那么戏剧性的解决方法。

首先:不,你不能降低选择器的特异性。选择子不提供任何具有负特异性水平的特征,这些特征水平会以这种方式降低特异性。你可以去的最低点是*,它具有特异性(即它不会使复杂的选择器具体或多或少)。

所以你在选择器级别上唯一的办法是增加它。是否可以在不使用黑客的情况下执行此操作取决于您对“黑客”的定义。

以下是我认为是hack的内容,因为它使用了一个语法上合法但语义无意义的选择器,如:not(_),没有明显的目的,只是为复杂的选择器添加一个类型选择器的特异性(这对于没有经验的人来说远非显而易见):

.special-section p { }
.weird-font, :not(_).weird-font { }

以下是我认为是黑客攻击,因为无论如何你都会做正常的事情。几乎唯一的“问题”在于它是一个明显重复的单一类选择器:

.special-section p { }
.weird-font, .special-section p.weird-font { }

如果为了提高特异性而考虑任何类型的无关选择器 - 黑客 - 这是一个完全合理的POV,不要搞错 - 那么不是黑客的下一个最好的事情是!important

就个人而言,我会选择特异性黑客。 !important具有特定黑客攻击的重要重要影响 - 请记住!important and specificity have different semantics。例如,您不能使用内联样式或JavaScript覆盖!important声明,除非它们也被标记为重要。 1

1 事实上,这是我对Lea Verou的回应,当时她有discussion on Twitter一段时间关于特异性黑客攻击!important

答案 2 :(得分:3)

如今,在2018年,这几乎是有可能的。

首先,CSS4将提供一种方法,使您可以创建更具体的选择器而无需增加特异性:

:where(.special-section) p {
    color: red;
}

这会将.special-section中的段落颜色设置为红色,但特异性为001(即与普通p选择器具有的特异性相同)。

spec仍调用此特殊的伪类:something(),但称为chances are it's going to be called :where()。 (旁注:我真的want这就是所谓的“蜜badge选择器”。)

但这仍然是未来。

但是,如果您不再需要支持IE(或者对效果不尽人意的后备感到满意),实际上就有一种方法可以实现今天的 ),也就是使用custom properties又称CSS变量。

所以你想要这个:

.special-section p { color: red; }
.weird-font        { color: magenta; }
p                  { color: green; }

,但第一部分的特异性低于其中包含类的任何选择器。您可以这样做:

.special-section p { --low-specificity-color: red; }
.weird-font        { color: magenta; }
p                  { color: var(--low-specificity-color, green); }

如果您在现代浏览器中运行以下代码段,则应注意第二段为红色,因为它位于特殊部分,而第三段为洋红色,因为它是.weird-font,即使{ {1}}具有010特异性,.weird-font具有011。

.special-section p
.special-section p { --low-specificity-color: red; }
.weird-font        { color: magenta; }
p                  { color: var(--low-specificity-color, green); }

之所以可行,是因为<p>This is a paragraph.</p> <section class="special-section"> <p>This is a paragraph inside a special section.</p> <p class="weird-font">This is a paragraph with a weird font inside a special section.</p> </section> <p class="weird-font">This is a paragraph with a weird font.</p> <div class="weird-font">This is a div with a weird font.</div>更改为011特异性后,仅应用了001特异性。

答案 3 :(得分:0)

我喜欢与当前必要一样具体。我想为将来的CSS更改留出空间,所以不要为了它而尽可能具体,例如:

.great-grandfather .grandfather .father .child { }

如果必须,我会的。但是以上面的例子为例,如果我想覆盖使用此类的特定元素的.child,该类具有可能是这样的样式:

.child {
   color: black;
}

如果可能的话,我会去上面的一位父母来覆盖它:

.father .child {
   color: white;
}

更进一步说明,如果特定网页上的某个元素使用.child类,在这种情况下,我需要覆盖.father .child,我会更进一步的特异性:

.grandfather .father .child {
   color: red;
}

这样做可以确保您不需要使用!important ......我尽可能地避免瘟疫!