When to use Sass mixins, extends and variables
Recently had a conversation on Twitter that reminded me that what is apparent to some old hats might be obscure to those just diving into Sass. Here are my rules of thumb on when to use mixins, extends, and variables.
Variables
Use a variable when you have a single value you'd like to store. For instance:
$color: #444;
$width: 4em;
.module {
color: $color;
}
Compiles to:
.module {
color: #444;
}
Extends
Use @extend
when you want to store multiple static properties and pass them to selectors:
.module {
background: #fff;
color: #444;
}
.main_module {
@extend .module;
min-height: 3em;
}
.sidebar_module {
@extend .module;
min-height: 2em;
}
Compiles to:
.module, .main_module, .sidebar_module {
background: #fff;
color: #444;
}
.main_module {
min-height: 3em;
}
.sidebar_module {
min-height: 2em;
}
Mixins
Mixins always compile to CSS rules where they appear in code. Where an @extend
generates more selectors, @mixin
always generates more rules. Observe the above as a mix-in:
@mixin module {
background: #fff;
color: #444;
}
.main_module {
@include module;
min-height: 3em;
}
.sidebar_module {
@include module;
min-height: 2em;
}
Compiles to:
.main_module {
background: #fff;
color: #444;
min-height: 3em;
}
.sidebar_module {
background: #fff;
color: #444;
min-height: 2em;
}
This is why for static rules it is often (not always) less bloaty to use @extend
.
As a rule of thumb, I only use mixins to do "mathy" things. "If it doesn't need to pass variable, it doesn't need to be a mixin" is my motto:
@mixin module($parent-color) {
color: darken($parent-color, 50%);
}
.main_module {
@include module(#ccc);
min-height: 3em;
}
.sidebar_module {
@include module(#444);
min-height: 2em;
}
Compiles to something like:
.main_module {
color: #999;
min-height: 3em;
}
.sidebar_module {
color: #000;
min-height: 2em;
}
Written by Rachel Nabors
Related protips
12 Responses
Thanks for the succinct explanation of the differences.
If I want to use a set of rules and @extend them, but don't want the base class to show up anywhere, I use the "%" operator.
%module { } means that the class ".module" won't show up in the output anywhere.
@pe1999 Exactomundo!
@pe1999 Exactomundo!
I would also use a mixin for something like clearfix or other css hack.
@dpashkevich A SASS tool like Compass helps in this avenue, as it has many, many common ones built in, plus other useful mixins like responsive grid libraries (We recommend Susy). Worth checking out if you are not familiar.
@dpashkevich I beg to differ. I use an extend class for that. Keep selectors short and DRY.
%clearfix { zoom: 1; /*or whatevs*/ }
.container { @extend %clearfix; }
Just works out better for me in the large codebases I've worked on. But that's me.
@pe1999 I'm familiar with Compass, I was just making a point that mixins can be used for "mixing in" some common snippets like clearfix. Thanks for the reference to Susy though!
@rachelnabors that's interesting, thanks for sharing! So the only difference here is that if my .container already has the properties defined in clearfix, they won't appear twice?
@dpashkevich Right. @extend
lets you extend selectors; @mixin
is a rules factory.
Really nice post. I dont usually use extend but I will definitely look into it.
Very nice. I'm learning Sass, this article will help me.
I use a function to do mathy things.
margin: emCalc(10px) would return the em value for the px I use.
In the example of a mixin you have given above, I would have used a function.
Mixins, to me, generally give out a set of CSS rules.
Functions return values that are used inside of a property.
@extend and @include are a great source of confusion. If you have the same item being repeated multiple times (say 50 or above), using @extend could bloat up the selector list on your CSS. Its great for shortening the output and the browsers understand it better.
Unless you're debugging Sass, if you're debugging CSS, you might find it extremely difficult to locate the particular rule declaration.
Because of this same reason, @extend does not work well for grid scss files.
Sometimes it makes more sense to use an @include when you want the output to be together.
Very helpful and succinct explanation. Thanks.