Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to use @extend and @mixin in Sass

Tags:

css

sass

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.

  1. @mixin can take the arguments(but @extend cannot?), which is good, it works like a function.
  2. @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?

like image 804
FullStackDeveloper Avatar asked Aug 26 '17 21:08

FullStackDeveloper


2 Answers

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.

like image 127
Alessio Avatar answered Nov 14 '22 05:11

Alessio


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

like image 4
codejockie Avatar answered Nov 14 '22 05:11

codejockie