SCSS Extend and Mixin
Introduction
@extend
can produce more compact CSS than a mixin
, but tends to make your stylesheets more difficult to maintain. Below are some examples to help you think through the pros and cons.
The main thing to keep in mind while deciding which of these to use is, “how easy will this be maintain?”
TL;DR
You should use @extend
only if:
- You’ve got an existing class that already has most of what you need.
- It exists nearby in the same document.
- It is immediately obvious what you are extending and why.
There are a few exeptions to these rules …but very few.
Extend Example
SCSS:
.row {
display: flex;
flex-wrap: wrap;
margin-right: -15px;
margin-left: -15px;
}
.new-row {
@extend .row;
max-width: 1200px;
}
.another-row {
@extend .row;
max-width: 1400px;
}
Compiled CSS:
.row,
.new-row,
.another-row {
display: flex;
flex-wrap: wrap;
margin-right: -15px;
margin-left: -15px;
}
.new-row {
max-width: 1200px;
}
.another-row {
max-width: 1400px;
}
Mixin Example
SCSS:
@mixin row {
display: flex;
flex-wrap: wrap;
margin-right: -15px;
margin-left: -15px;
}
.new-row {
@include row;
max-width: 1200px;
}
.another-row {
@include row;
max-width: 1400px;
}
Compiled CSS:
.new-row {
display: flex;
flex-wrap: wrap;
margin-right: -15px;
margin-left: -15px;
max-width: 1200px;
}
.another-row {
display: flex;
flex-wrap: wrap;
margin-right: -15px;
margin-left: -15px;
max-width: 1400px;
}
A mixin
includes the properties everywhere it is included—making a copy each time—whereas an @extend
groups the selectors and defines the properties once. You might think using a mixin
creates unnessasary duplication, but again, you need to ask yourself “how easy will this be maintain if I use @extend
?”
The difference in the compiled CSS has some important implications:
Load Order
With @extend
the selectors will be grouped in the compiled CSS where the extended selector is defined. This can cause some unintended overrides.
Consider this example:
HTML:
<div class='row highlight-row'></div>
SCSS:
.red-text {
color: red;
}
.row {
color: green;
}
.highlight-row {
@extend .red-text;
}
Compiled CSS:
.red-text,
.highlight-row {
color: red;
}
.row {
color: green;
}
So even though the Sass ordering makes it look like the row color would be red, the compiled CSS will make it green.
Groupings
@extend
can result in difficult to read groups of selectors in the compiled CSS. You can end up with many classes all sharing the same declarations. Here is an example from a live Travel Tripper website:
In case it wasn’t immediately obvious, this is an example of what not to do.
Nesting
If you are using deeply nested Sass and you use @extend
you will duplicate the fully nested selector for every @extend
, resulting in bloated CSS:
.selector-1 .selector-2 .selector-3 .selector-4,
.selector-1 .selector-2 .selector-3 .selector-4 a,
.selector-1 .selector-2 .selector-3 .selector-4 li,
.selector-1 .selector-2 .selector-3 .selector-4 td {
font-family: ariel;
}
Media Queries
@extend
does not work inside media queries—media queries are not selectors.
Good Use Examples
There are only a couple good use cases for @extend
. Here are two examples:
Buttons
Buttons tend to be an iffy use case for @extend
. You could add common styles to .button
and add color and font differences to .button-primary
, for example, then add class="button button-primary"
to your markup. Using @extend
also works, and would only require a single class selector:
%button {
padding: 10px 25px;
font-family: "Font One", "Font Two";
font-size: 12px;
font-weight: 700;
text-transform: uppercase;
background-color: #fff;
border: 2px solid #fff;
}
.button-primary {
@extend %button;
color: $color-primary;
}
.button-secondary {
@extend %button;
color: $color-secondary;
}
Headers
A more useful example is probably headers. You might have two headers in your design files with the only difference being margin or font size.
.page-title {
margin: 80px auto;
padding-right: 15px;
padding-left: 15px;
font-family: $font-family-header;
font-size: 43px;
color: #fff;
text-transform: uppercase;
}
.display-title {
@extend .page-title;
margin-top: 0;
}
References
Offical Sass Guide: https://sass-lang.com/guide
Offical Sass Reference: http://sass-lang.com/documentation/file.SASS_REFERENCE.html
The Extend Concept: https://css-tricks.com/the-extend-concept/
What Nobody Told You About Sass @extend: https://www.sitepoint.com/sass-extend-nobody-told-you/
When to Use @extend; When to Use a Mixin: https://csswizardry.com/2014/11/when-to-use-extend-when-to-use-a-mixin/