Last Updated: January 26, 2021
·
49.11K
· rachelnabors

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

12 Responses
Add your response

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.

over 1 year ago ·

@pe1999 Exactomundo!

over 1 year ago ·

@pe1999 Exactomundo!

over 1 year ago ·

I would also use a mixin for something like clearfix or other css hack.

over 1 year ago ·

@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.

over 1 year ago ·

@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.

over 1 year ago ·

@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?

over 1 year ago ·

@dpashkevich Right. @extend lets you extend selectors; @mixin is a rules factory.

over 1 year ago ·

Really nice post. I dont usually use extend but I will definitely look into it.

over 1 year ago ·

Very nice. I'm learning Sass, this article will help me.

over 1 year ago ·

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.

over 1 year ago ·

Very helpful and succinct explanation. Thanks.

over 1 year ago ·