Search code examples
sassextend

Sass fails to @extend selectors created with the parent selector


I need to create CSS output done with SCSS and placeholder in a certain way

This is the output that I want

.myclass {
  color: silver;
}
.myclass-gold {
  color: gold;
}

When I try this with a SCSS placeholder like this

%placeholder {
  color: silver;
  #{&}-gold {
    color: gold;
  }
}

.myclass {
  @extend %placeholder !optional;
}

I only get this result

.myclass {
  color: silver;
}

The gold part is dropped altogether.


I need a placeholder, because I use many selectors like a.myclass, input.myclass etc and don't want the exploded @export from these

If I do not use a placeholder but a random selector—and take some extry bytes—the output is not right, either

ae739ab7 {
  color: silver;
  #{&}-gold {
    color: gold;
  }
}

.myclass {
  @extend ae739ab7 !optional;
}

yields

ae739ab7, .myclass {
  color: silver;
}
ae739ab7 ae739ab7-gold, .myclass ae739ab7-gold {
  color: gold;
}

and

ae739ab7 {
  color: silver;
  &-gold {
    color: gold;
  }
}

.myclass {
  @extend ae739ab7 !optional;
}

gives me

ae739ab7, .myclass {
  color: silver;
}
ae739ab7-gold {
  color: gold;
}

What's missing here is always the selector .myclass-gold

Is this possible somehow with some magic trick?


Solution

  • Extends only work on exact matches. When you write this:

    %placeholder {
      color: silver;
      #{&}-gold {
        color: gold;
      }
    }
    

    What you've really created is this:

    %placeholder {
      color: silver;
    }
    
    %placeholder %placeholder-gold {
      color: gold;
    }
    

    So when you write this:

    .myclass {
      @extend %placeholder !optional;
    }
    

    It will only extend the %placeholder selector and not %placeholder-gold selector. To get the behavior you're looking for, you have to extend each placeholder selector individually:

    %placeholder {
      color: silver;
      @at-root #{&}-gold {
        color: gold;
      }
    }
    
    @mixin placeholder {
        & {
            @extend %placeholder;
            @at-root #{&}-gold {
                @extend %placeholder-gold;
            }
        }
    }
    
    .myclass {
      @include placeholder;
    }
    

    Output:

    .myclass {
      color: silver;
    }
    .myclass-gold {
      color: gold;
    }