SassSelectors

How to extend parent selectors in Sass

Using Sass to extend nested parent selectors

Introduction

Sass' @extend rule allows you to copy the properties of one selector's rule into another.

There are often cases when designing a page when one class should have all the styles of another class, as well as its own specific styles.

For example, you might want to create a component of perfectly square; squares, for which you might use a class named .square.

However, what if you wanted separate classes for squares of different colours? Enter the @extend rule. It tells Sass that one selector should inherit the style properties of another:

.square
  width: 100px
  height: 100px
  background-color: black

.square-blue
  @extend .square
  background-color: blue !important

.square-red
  @extend .square
  background-color: red !important

After running this, the Sass code for our square component is transpiled into CSS as:

.square, .square-blue, .square-red {
  width: 100px;
  height: 100px;
  background-color: black;
}

.square-blue {
  background-color: blue !important;
}

.square-red {
  background-color: red !important;
}

The thing is, Sass doesn't allow selectors to inherit the styles of another selector if the "inheriting selector" is a nested child of the parent.

To demonstrate, let's extend a .child selector with a .parent selector using the Sass parent selector (&):

.parent
  width: 100%
  height: 100%
  font-wight: bold
  .child
    @extend &

Which throws a Parent selectors aren't allowed here error:

Parent selectors aren't allowed here.
   ╷
 6 │    @extend &
   │            ^
   ╵
   stdin 6:20  root stylesheet on line 6 at column 14

This is because a child selector extended with its parent's selector would create an infinite loop wherein the child would inherit the parent's styles and then its own styles recursively.

CSS selector lists

The first way of getting around this error is to refactor the code and use Sass' parent selector (&) and CSS selector lists to apply the property to both the parent and the child, thus avoiding the need to create two rules for the same element.

.parent
  background-color: #F9F9F9
  &, .child
    font-style: italic

Result:

.parent {
  background-color: #F9F9F9;
}
.parent, .parent .child {
  font-style: italic;
}

Sass placeholder selectors

Another way is to use Sass placeholder selectors to create a set of common properties and then use the @extend rule to extend both parent and the child with common properties:

%common
  font-style: italic

.parent
  @extend %common
  background-color: #F9F9F9
  .child
    @extend %common

Result:

.parent, .parent .child {
  font-style: italic;
}

.parent {
  background-color: #F9F9F9;
}