Both @mixin
and @extend
seem to have the same goal:
Add a block of default code for a class.
But if they have this same purpose, what is the difference between them? And when should I use one or the other?
Both @mixin
and @extend
seem to have the same goal:
Add a block of default code for a class.
But if they have this same purpose, what is the difference between them? And when should I use one or the other?
The use of @mixin
and @extend
may appear similar and have the same purpose, although true, they have different purposes as well as their pros and cons. Both, if used in the wrong way, can become a bad headache.
At first we may tend to use one or the other in the hills because of the practicality they give us to write SASS
. With @mixin
or @extend
you can summarize numerous lines of code. But that's where the danger lies ..
Often what we write in SASS
seems perfectly practical and perfect, everything seems in order, keeping the principle of DRY
, but everything goes away when we look at our compiled code for CSS
.
For example, the following code may look perfect on SASS
:
@mixin placeHolder {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe1 {
@include placeholder;
}
.classe2 {
@include placeholder;
}
.classe3 {
@include placeholder;
}
.classe4 {
@include placeholder;
}
.classe5 {
@include placeholder;
}
But the CSS
generated would be this:
.classe1 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe2 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe3 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe4 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe5 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
The whole principle DRY
, code maintenance and simplicity that in SASS
seemed perfect, went by water ...
But that's where @extend
comes to salvation! See the same logic with the use of @extend
:
%placeHolder {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
.classe1 {
@extend %placeHolder;
}
.classe2 {
@extend %placeHolder;
}
.classe3 {
@extend %placeHolder;
}
.classe4 {
@extend %placeHolder;
}
.classe5 {
@extend %placeHolder;
}
Generating the following code:
.classe1,
.classe2,
.classe3,
.classe4,
.classe5 {
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
Perfect, now we can keep the code simple, clean, in a few lines of code.
Although this is true, it is a partial truth. The use of @extend
when done abusively can break the whole basic principle of its use and generate many classes with few properties, making its final code extremely messy, with repetition of classes, going back to square one.
But what should I use? And when should I use?
A basic trick I like to remember is this:
For example, suppose you have a button with the same style but with some color states. You could do this as follows:
@mixin corBotao($cor, $corHover) {
border: 1px solid $cor;
color: $cor;
&:hover {
background: $cor;
color: $corHover;
}
}
.button--azul {
@include corBotao(blue, white);
background: transparent;
width: 64px;
height: 48px;
cursor: pointer;
text-align: center;
}
In this way you will generate the following code:
.button--azul {
background: transparent;
width: 64px;
height: 48px;
cursor: pointer;
text-align: center;
/* Gerado pelo mixin */
border: 1px solid blue;
color: blue;
&:hover {
background: blue;
color: white;
}
}
With this you can generate several buttons with different colors without having to manually define which color each button will have.
To illustrate the use of @mixin
, you can start from the same example above and improve our code. The properties of width
, height
, etc ... are common on all buttons, be it blue, red, green, etc ... Then just these properties we can convert to use @extend
:
@mixin corBotao($cor, $corHover) {
border: 1px solid $cor;
color: $cor;
&:hover {
background: $cor;
color: $corHover;
}
}
%padraoBotao {
background: transparent;
width: 64px;
height: 48px;
cursor: pointer;
text-align: center;
}
.button--azul {
@include corBotao(blue, white);
@extend %padraoBotao;
}
.button--verde {
@include corBotao(green, white);
@extend %padraoBotao;
}
.button--vermelho {
@include corBotao(red, white);
@extend %padraoBotao;
}
The above example will generate the following final code:
.button--azul,
.button--verde,
.button--vermelho {
background: transparent;
width: 64px;
height: 48px;
cursor: pointer;
text-align: center;
}
.botao--azul {
border: 1px solid blue;
color: blue;
&:hover {
background: blue;
color: white;
}
}
.botao--verde {
border: 1px solid green;
color: green;
&:hover {
background: green;
color: white;
}
}
.botao--vermelho {
border: 1px solid red;
color: red;
&:hover {
background: red;
color: white;
}
}
See how the final code has stayed clean, organized, objective, and maintaining best practices.
What would not be recommended, would be to use the same extend for another element, even though it has the same characteristic.
Another example that I particularly use @mixin
is for small codes that will be used in some classes, for example the use of display: flex;
. Since we still need vendor-prefix
, I do not want to write all of them by hand, but I also do not want to generate an unrelated grouping of classes, just by sharing the same display
. For this I use a mixin, but it is a controlled use with a very specific purpose.
As seen in the examples, each has a very specific and intended use. Although they are similar DENTRO DO SASS
, when we look at our CSS
they have very distinct results that can worsen their final code rather than improve.
But despite all this difference, remember that it's not a rule to be followed (as I myself break it from time to time), it's all about planning and organizing your code.
For more good practice guides on CSS
and SASS
recommend see this project I'm working out in github
, it is in constant development and I also accept contributions! In fact, they are more than welcome. More experiences generate best practices.