When it comes to comparing @extend
and mixins, one of the key differences lies in how the CSS is compiled. While the variance may not seem significant in basic examples, the implications can be substantial and lead to headaches if used carelessly. Think of @extend
as akin to fool's gold - initially appealing, but...
Let's illustrate with a simple example:
@extend
.row {
width: 50px;
}
.new-row {
@extend .row;
}
.another-row {
@extend .row;
}
Compiles to:
.row,
.new-row,
.another-row {
width: 50px;
}
Mixin
@mixin row() {
width: 50px;
}
.new-row {
@include row();
}
.another-row {
@include row();
}
Compiles to:
.new-row {
width: 50px;
}
.another-row {
width: 50px;
}
A mixin duplicates properties each time they are called, whereas @extend
groups selectors and defines properties just once. This distinction may not be immediately apparent since it affects the compiled CSS, but it carries some important consequences:
Load Order
With @extend
, selectors are grouped where first encountered in the SCSS, which can result in unexpected overriding. For instance, attempting to override a property defined earlier in your SCSS file after the grouping by @extend
will not work as anticipated.
Consider this logically-ordered CSS set with corresponding HTML:
<div class='row highlight-row'></div>
:
.red-text {
color: red;
}
.row {
color: green;
}
.highlight-row {
@extend .red-text;
}
Compiles to:
.red-text,
.highlight-row {
color: red;
}
.row {
color: green;
}
Even though the order suggests the text should be red, the compiled CSS makes it green.
Poor Groupings
@extend
can lead to poorly organized selectors in the resulting CSS, with unrelated items sharing the same properties. Fonts are a common example of this issue when using @extend
.
Nesting
If you have deeply nested SASS (which is generally discouraged), using @extend
can result in bloating the CSS with duplicated fully-nested selectors for every @extend
used.
.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: arial;
}
For SASS newcomers, examining the compiled CSS is highly advisable.
Media Queries
@extend
does not function within media queries because media queries are not selectors.
Conclusion
As a general rule, use @extend
over mixins without parameters if you can define the extension reasonably and share it among closely-related selectors nearby in the SASS file. Buttons are a prime example of proper usage of @extend
:
%button {
padding: 10px;
}
.call-to-action {
@extend %button;
background-color: $green;
}
.submit {
@extend %button;
background-color: $grey;
}
To make an informed decision, refer to the comprehensive article available here.
PS: The %
symbol corresponds to placeholder extensions.