10

I'm using stylelint with the standard format stylelint-config-standard and I'm encountering this error a lot with my stylesheets:

no-descending-specificity

An example of where it's happening is when I have CSS like:

.footer__social li a {}

.footer__social li a:hover {}

.footer__links li a {}

.footer__links li a:hover {}

and then I get the following error:

Expected selector ".footer__links li a" to come before selector ".footer__social li a:hover" no-descending-specificity.

A lot of the CSS will be like this because of using SASS like:

.footer__links {
  a {
    a:hover {}
  }
}

I don't want to have disable this if I can...

But why is it complaining? as it's two separate classes: .footer__social and .footer__links.

So these two declarations for the anchors don't have any effect on each other because they have different parent classes so what's the issue? I'd understand something like:

.footer__links a:hover {}
a {}

But I don't see the issue if it's two different classes...

Cameron
  • 27,963
  • 100
  • 281
  • 483
  • Who says they have any effect on each other? They don't. What Stylelint is telling you is that you have a rule with higher specificity in your rule sheet that is above one with a lower specificity. Stylint is right, you do. – Seth Warburton Sep 10 '19 at 13:20
  • Further discussion see [Fix false positives for pseudo classes in no-descending-specificity](https://github.com/stylelint/stylelint/issues/4271) – Ingo Steinke Nov 15 '21 at 15:04
  • Stylelint is right, but not helpful. The specification of the rule is too fuzzy by design. – Ingo Steinke Jul 19 '23 at 11:40

2 Answers2

7

As Stylint is advising you .footer__social li a:hover {} has a higher specificity (0-1-2 = 3) than the rule that follows it .footer__links li a {} (0-0-2 = 2). You can use this specificity calculator to confirm this.

Source order is important in CSS, hence the warning. This rule cares about specificity, 3 is higher than 2.

From the Stylelint docs (emphasis added):

Here's how it works: This rule looks at the last compound selector in every full selector, and then compares it with other selectors in the stylesheet that end in the same way.

To satisfy the noDescendingSpecificity rule your output would need to be in the order:

.footer__social li a {}

.footer__links li a {}

.footer__social li a:hover {}

.footer__links li a:hover {}

Though personally I would also sort my rules alphabetically, as that is a) better for my OCD and b) allows for slightly better compression with gzip, e.g:

.footer__links li a {}
.footer__social li a {}
.footer__links li a:hover {}
.footer__social li a:hover {}
Seth Warburton
  • 2,234
  • 1
  • 16
  • 17
  • 7
    But in a component based setup this isn't feasible. And if you use SASS to group stuff then this is also not feasible... – Cameron Sep 10 '19 at 13:11
  • I'd argue that it is is feasible. Nonetheless, it is the answer to your question. Your options are 1) disable the rule, 2) re-order your rules or 3) live with the warnings. – Seth Warburton Sep 10 '19 at 13:15
  • I'm not sure what you expect here, that the authors of Sass and Stylelint have the same goals? If you don't like the tool, don't use it. If you have a complaint about the way Stylelint works take it up with the author. I believe I have answered your question, but I cannot answer your follwo-up questions on behalf of the authors of either Sass or Stylelint; I am neither. – Seth Warburton Sep 10 '19 at 14:13
  • If my answer is correct, kindly mark it as so. If you have other questions, post them as separate questions either here or with the authors of said tools. – Seth Warburton Sep 10 '19 at 14:15
3

You can skip this rule by adding the stylelint disable commenad to the top of the file

/* stylelint-disable no-descending-specificity */
// your styles
/* stylelint-enable no-descending-specificity */
techloris_109
  • 547
  • 5
  • 13
  • Adding a disable comment will suppress the warning no matter if it's a false positive or if it actually makes sense. – Ingo Steinke Jul 19 '23 at 11:41