4

Given the following HTML / SASS code:

<div class="a">hello</div>

%color {
    color: blue;
}
.a {
  color: red;
}
.a.a {
  @extend %color;
}

I was expecting the resulting color to be blue (due to the more specific .a.a selector1) with output something like this:

.a.a {
   color: blue;
}
.a {
   color: red;
}

But actually, the resulting color is red, with SASS output:

.a {
  color: blue;
}

.a {
  color: red;
}

I find this quite counter-intuitive!

Why does SASS refactor my .a.a selector to .a?

Just in case you don't believe me, here's a codepen demo (click view compiled css to see the CSS output)

NOTE:

This 'refactoring' of the selector only occurs to the declarations within the extend.

So in the following SASS:

%color {
    color: blue;
}
.a.a {
  @extend %color;
  position: relative;
}

The output is:

.a {
  color: blue;
}

.a.a {
  position: relative;
}

(Codepen demo)


1See the spec:

Note: Repeated occurrences of the same simple selector are allowed and do increase specificity.

Danield
  • 121,619
  • 37
  • 226
  • 255
  • I think that SASS is reasoning that an element with a class name of "a" as well as a class name of "a" is the same as an element with a class name of "a". – Mr Lister Oct 24 '18 at 10:27
  • On the other hand, this happens only in the presence of `@extend`. Hm. – Mr Lister Oct 24 '18 at 10:29
  • I guess this would be example of SASS preprocessor's optimizing your code. – Kizivat Oct 24 '18 at 10:29
  • In css `.a` and `.a.a` are identical, so SASS intelligently saves some bytes. – connexo Oct 24 '18 at 10:31
  • 2
    @connexo no, they aren't identical, one is more specific than the other – Temani Afif Oct 24 '18 at 10:32
  • 1
    @connexo But they are not! `.a.a` has a higher specificity! Change the OP's SCSS to `.a { color: red; &.a { color: blue; } }` and see the color change! – Mr Lister Oct 24 '18 at 10:32
  • It makes absolutely zero sense that `.a.a` would by any means make the rule more specific than `.a`. If that is true (haven't checked), it's clearly an error/misdesign in the specification. Besides `.a.a` being really bad code, but that's another issue. – connexo Oct 24 '18 at 10:35
  • btw at [SASS Meister](https://www.sassmeister.com/) it is compiled correctly even with `@extend`. Try updating SASS. – Kizivat Oct 24 '18 at 10:38
  • related : https://github.com/sass/sass/issues/1596 ... old but also related: https://github.com/sass/sass/issues/324 – Temani Afif Oct 24 '18 at 10:38
  • 2
    @connexo *It makes absolutely zero sense* : this is how specifity always worked (https://stackoverflow.com/questions/2809024/points-in-css-specificity) and this is something we can use in order to override some external style like doing `.a:not(#random_ID)` [we increase the speficity using an ID without changing the rule] – Temani Afif Oct 24 '18 at 10:39
  • Trying to win a specificity war by concatenating the same class selector multiple times seems like a really dumb approach. – connexo Oct 24 '18 at 10:41
  • 3
    @connexo the issue is not there. A bad approach or not, the compiler shouldn't change the specifity that the user defined. Optimization shouldn't affect the behavior. – Temani Afif Oct 24 '18 at 10:44
  • @TemaniAfif Agreed, especially all the SASS compiles should reliably create identical results with regard to how the result works. – connexo Oct 24 '18 at 10:45
  • @connexo While I understand your frustration, it's no use saying "but this feature makes no sense" as if other features in CSS do make sense! – Mr Lister Oct 24 '18 at 10:48

1 Answers1

0

By the looks of it, the result depends on the parsing engine. If you use DartSass v1.6.2 (default on sassmeister.com), it outputs your expected result:

.a.a {
  color: blue;
}

.a {
  color: red;
}

Check on sassmeister.com (you can also switch parsing engines there).

LibSass v3.5.2 creates the result you complained about:

.a {
  color: blue;
}

.a {
  color: red;
}
Nick
  • 3,231
  • 2
  • 28
  • 50
connexo
  • 53,704
  • 14
  • 91
  • 128