I am learning Sass in its official tutorial.
When I learned @mixin
and @extend
, I know both of them is for CSS code reuse, but I just cannot figure out when to use which one. There are two differences for me.
@mixin
can take the arguments(but @extend
cannot?), which is good, it works like a function.@extend
can make your output CSS contains less code, like this output CSS (.message, .success, .error, .warning { })
in its official tutorial. Currently, I only know that, if I want to take extra arguments, I will use @mixin
. If I want to have less output CSS code, I will use @extend
. Except those two, I can pick either one to use. Am I correct?
You are on the right way.
You should use a mixin when you want the output to change depending on how you call it.
So, in some cases using a %placeholder
and @extend
would have produced less CSS.
It is important to realise that @extend creates relationships. Whenever you use @extend
, you are transplanting a selector elsewhere in your stylesheet in order for it to share traits with other selectors that are also being transplanted.
EXTEND
e.g.
.awesome {
width: 100%;
height: 100%;
}
body {
@extend .awesome;
}
p {
@extend .awesome;
}
Which returns:
.awesome, body, p {
width: 100%;
height: 100%;
}
MIXIN
@mixin awesome {
width: 100%;
height: 100%;
}
body {
@include awesome;
}
p {
@include awesome;
}
Will return:
body {
width: 100%;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
But with mixins you can have parameters like:
@mixin awesome($w: 100%, $h: 100%) {
width: $w;
height: $h;
}
body {
@include awesome(960px);
}
p {
@include awesome;
}
Which returns:
body {
width: 960px;
height: 100%;
}
p {
width: 100%;
height: 100%;
}
Hope this was helpful!
Additional:
The @extend
directive isn’t flexible. You can’t pass arguments to it so what’s there is there. There are also limitations on using @extend
inside @media
directives and you can’t extend a selector across different media directives using @extend
.
The main advantage to using mixins is the power and flexibility they have because they can accept arguments. Naturally, if you want to pass arguments, you’ll have to choose @mixin
over @extend
.
They are kind of interchangeable, it depends also if you want/have to stick to DRY CSS or not.
EXTEND
%hide-text {
text-indent: -9999px;
overflow: hidden;
}
.foo {
@extend %hide-text;
}
.bar {
@extend %hide-text;
}
.baz {
@extend %hide-text;
}
Nice and clean result:
.foo, .bar, .baz {
text-indent: -9999px;
overflow: hidden;
}
MIXIN
@mixin hide-text {
text-indent: -9999px;
overflow: hidden;
}
.foo {
@include hide-text;
}
.bar {
@include hide-text;
}
.baz {
@include hide-text;
}
Result:
.foo {
text-indent: -9999px;
overflow: hidden;
}
.bar {
text-indent: -9999px;
overflow: hidden;
}
.baz {
text-indent: -9999px;
overflow: hidden;
}
You can see there's no relation between the CSS selectors.
@extend
extends rules inside of rules in essence creating inheritance.
.button {
color: black;
}
.submit-button {
@extend .button;
border 1px black solid;
}
Results in:
.submit-button {
border: 1px black solid;
}
.button, .submit-button {
color: black;
}
Use @extend
when you want to inherit a rule
@mixin
creates repeatable sections of code, more like functions
@mixin large-font {
font: {
size: 14px;
family: san-serif;
weight: bold;
}
}
#form {
@include large-font;
}
Use @mixin
when you know you'll be repeating yourself a lot. Creating @mixin
helps you avoid that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With