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;
}