SCSS - override @extend with another @extend

A common problem I'm having with @extend is trying to override the inherited properties with another @extend .

Here is an example:

 // class selectors to be @extended // these could also use % to be silent/placeholder selectors .size-2xl { @include rem(font-size, 40px); } .size-3xl { @include rem(font-size, 60px); } // mapping the class selector properties onto some structural classes .heading1 { @extend .size-3xl; } .heading1-small { @extend .heading1; @extend .size-2xl; } 

When SCSS is compiled, .heading1 and .heading1-small will get the correct properties, but .heading1-small will be too large.

This happens when the @extend -able class maps to several different selectors.

When SCSS is compiled into CSS, the various selectors are combined into one or more rule sets with multiple selectors.

Sometimes SCSS seems to be compiled β€œout of order”, so the compiled .heading1 selector is output after the .heading1-small selector.

It could even be a nested @extend causing this behavior.

What is the best way to avoid this situation? Some things that I can think of from my head are as follows:

  • use @include('size-2xl') (less than DRY)
  • not @extend rules containing @extend (restricts use of @extend)

Thanks.

+6
source share
1 answer

The ruleset in the output CSS is in the same place / order / sequence as they were defined in SCSS, since you only output the extended ruleset .size-2xl and .size-3xl . Therefore, you need to switch the locations of these two rule definitions (see demo ) or define size rules as mixins and include them in the header rules (see demo ). So, I think you must be @extend something about how @extend works.

If you have something like this:

 .class1 { foo: bar1; } .class2 { foo: bar2; @extend .class1; } 

You add the .class2 selector to an existing rule set using the .class1 selector - so the output will look like this:

 .class1, .class2 { foo: bar1; } .class2 { foo: bar2; } 

However, if we do not add any new properties to .class2 , we simply use @extend :

 .class1 { foo: bar1; } .class2 { @extend .class1; } 

The .class2 rule .class2 will not print in CSS, and only the selector will be added to .class1 - hence the output:

 .class1, .class2 { foo: bar1; } 

This is more or less what you do by simply adding the .header1 and .header2 to the .size-2xl and .size-3xl , so the output will be in the same place / order in which these rules are defined in SCSS.

So what you get at the end in your example:

  • you define a .size-2xl and .size-3xl
  • you add the .header1-small selector to the .size-2xl rule sets
  • you add the .header1-small selector to the .header1 selector and add both parameters to the .size-3xl rule set
  • ruleset .size-2xl (now after extension: .size-2xl, .header1-small ) prints in CSS
  • ruleset .size-3xl (now after extension: .size-3xl, .header1, .header1-small ) prints in CSS
  • ruleset .header1 (also extended .header1, .header1-small ) does not print because it does not have specific properties
  • ruleset .header1-small does not print because it does not have specific properties

Another note:. The same thing will happen when using placeholders ( % ), which can be even more confusing, for example, in .size-3xl, .header1, .header1-small .size-3xl will be invisible, but in CSS it’s all the same will be compiled where the .size-3xl rule was defined in SCSS.

+15
source

Source: https://habr.com/ru/post/956597/


All Articles