【问题标题】:Nesting CSS selectors without increasing specificity嵌套 CSS 选择器而不增加特异性
【发布时间】:2016-03-29 19:19:35
【问题描述】:

让我们来看看这三个选择器,从高到低排序:

.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,而不必使用黑客来增加选择器的特异性,例如.weird-font。我宁愿使用 hack 来降低 .special-section p 的特异性,也不愿使用 hack 来增加 .weird-font 的特异性。有没有办法做到这一点?

【问题讨论】:

  • !important 的问题是只有一层覆盖。如果你制作了一个更具体的选择器,你可以用一个更具体的选择器再次覆盖它。使用!important 后,你别无选择。
  • 添加类然后由它们选择不是一个技巧;这是选择元素的定义方式。如果您有一些示例标记,则用例可能会更清楚。
  • @TylerH:这不是 OP 所指的。您真的不需要示例标记来推断在示例 CSS 中,p 和 .weird-font 指的是同一个元素。
  • @BoltClock 我不同意;我完全不清楚 OP 的标记会是什么样子。即使通过巨大的努力,我们可以做出一个假设(所有答案都是如此),但通过一个简单的标记示例,它会变得更清晰、更容易理解(因此对其他人有帮助)。此外,如果我们知道标记,我们可以提供一种潜在的替代方法来实现 OP 的目标。例如,接受的答案与 OP 想要的完全相反(它在他想要避免增加特异性的地方增加了特异性)。
  • @TylerH:我不否认总有改进的余地,但考虑到 only 的情况,做出这样的假设并不需要“很大的努力”当两个选择器都引用同一个元素时,甚至适用于特殊性。接受的答案和我自己的建议都建议增加而不是减少它,因为你 can't 减少它,并且对于 OP 的问题没有任何其他解决方案不依赖于标记(而且,显然,OP 对这样的解决方案也不是很感兴趣,这也是 fine)。

标签: css css-selectors css-specificity


【解决方案1】:

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

.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 大师。 ;)

【讨论】:

    【解决方案2】:

    作为一名 CSS 专家,我很遗憾放弃选择器必须提供的所有内容,以避免出现特殊性问题。这并不是说我不相信特异性机制有缺陷,但肯定有不那么引人注目的解决方法。

    首先:不,您不能降低选择器的特异性。选择器不提供任何具有负特异性水平的特征,这些特征会以这种方式降低特异性。您可以使用的最低值是*,它具有 特异性(即它不会使复杂的选择器变得或多或少地具有特定性)。

    所以你在选择器级别上唯一的办法就是增加它。不使用 hack 是否可以做到这一点取决于您对“hack”的定义。

    以下是我认为的 hack,因为它使用了一个语法上合法但语义上无意义的选择器,例如 :not(_),它没有明显的目的,只是将类型选择器的特殊性添加到复杂选择器(即远非显而易见,尤其是外行):

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

    以下内容不是我认为是 hack,因为这是你通常会做的事情。几乎唯一的“问题”是它明显重复了单独的类选择器:

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

    如果您为了提高特异性而将任何类型的无关选择器视为 hack(这是一个完全合理的 POV,请不要误会),那么 不是 hack 的下一个最好的事情是!important.

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


    1事实上,这是我对 Lea Verou 的回应,当时她有一个 discussion on Twitter!important 相比的特异性黑客攻击。

    【讨论】:

    • 在旁注中,我是唯一一个发现 Twitter 上的讨论无法阅读的人吗?例如,在您链接的讨论中,我可以看到@LeaVerou 回复您说“好点”,但我看不到您最初说的是什么! imgur.com/lUzfW7g
    • @Flimm:哈,这就是为什么我说我对她的回应就是我的回答中给出的 :) 不是你——我将我的帐户设为私有是因为我停止使用 Twitter,但我仍然收到垃圾邮件通知.不好玩:(
    • AFAIK 你不能用任何类型的 CSS 覆盖 JavaScript 插入的 !important 属性。你需要更多的 JavaScript 才能做到这一点。
    • @TylerH:是的 - 我专门指的是 CSS 级别的 !important 声明。
    • @BoltClock 啊,“或 JavaScript”位让我失望 :-)
    【解决方案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这被称为“蜜獾选择器”)。

    但这仍是未来。

    然而,如果您不再需要支持 IE(或者对不太完美的回退感到满意),实际上有一种方法可以实现这一点今天 ),即使用custom properties aka 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); }
    

    如果你在现代浏览器中运行下面的 sn-p,你应该注意到第二段是红色的,因为它在一个特殊的部分,但第三段是洋红色的,因为它是 .weird-font -- 即使@ 987654333@ 具有 010 特异性,.special-section p 具有 011。

    .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>

    这是可行的,因为虽然 --low-specificity-color 被更改为 011 特异性,但它仅应用为 001 特异性。

    【讨论】:

    • :something(或任何名称)现在是我在科技领域期待的事情的首位!
    • 顺便说一下,为什么是“蜜獾选择器”。我知道它与!important 的相反之处,但我没有得到链接。
    【解决方案4】:

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

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

    如果必须,我当然会。但是以上面的例子为例,如果我想为使用此类的特定元素覆盖 .child,其样式可能如下所示:

    .child {
       color: black;
    }
    

    如果可能的话,我会去上面的一位家长覆盖它:

    .father .child {
       color: white;
    }
    

    再往下说,如果特定页面上的元素使用.child 类,在这种情况下我需要同时覆盖.father .child,我将再上一层:

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

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

    【讨论】:

    • 那么有没有办法实现与.parent child选择器相同的效果,但特异性较低?
    猜你喜欢
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    • 2010-12-28
    • 2018-12-10
    • 2016-05-04
    • 2012-05-25
    • 2013-01-14
    • 2019-05-05
    相关资源
    最近更新 更多