What’s the difference and when to use @mixin and @extend on SASS?

Asked

Viewed 3,726 times

2

Both the @mixin like the @extend seem to have the same goal:

Add a standard code block to a class.

But if they have the same purpose, what is the difference between them? And when should I use one or the other?

1 answer

7

The use of @mixin and @extend may seem similar and have the same purpose, although this is true, they have different purposes as well as their pros and cons. Both, if used incorrectly, can become a huge headache.

At the beginning we may tend to use one or the other to the hills due to the practicality they give us to write SASS. With a @mixin or @extend you can summarize numerous lines of codes. But that’s where the danger lies..

Often what we write in SASS seems perfectly practical and perfect, everything seems in order, maintaining the principle of DRY, but it all goes away when we look at our compiled code for CSS.

For example, the following code might 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 would be generated 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 down the drain...

But that’s where the @extend for 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 manage to keep the code simple, clean, in a few lines of code.

BUT.....

Although this is true, it is a partial truth. The use of @extend when done abusively can break all the basic principle of its use and generate many classes with few properties, making its final code extremely messy, with repetition of classes, back to square one.

But then which one should I use? And when should I use?

A basic trick I like to remember is this::

  • Mixin: Use to generate your code dynamically through variables;
  • Extend: Use for common elements but there will be little repetition;

For example, let’s assume that you have a button with the same style but with some color states. You could do it this way:

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

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, can from the same previous example and improve our code. The properties of width, height, etc.. They are common on all buttons, be it blue, red, green, etc. So only these properties can we convert to the use of @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 remained clean, organized, objective and maintaining good practices.

What would not be recommended would be to use the same extend for another element, even though it has the same feature.

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;. How we still need the vendor-prefix, I don’t want to write all of them by hand, but I also don’t want to generate a complemante grouping of unrelated 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 your final code instead of improving.

But despite all this difference, remember that it is not a rule to be followed to the letter (as I myself break it once and for all), everything is a planning and organization of your code.

For more best practice guides on CSS and SASS recommend see this project that I’m working on github, he is in constant development and also accept contributions! Incidentally, they are more than welcome. More experiences generate best practices.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.