DEV Community

loading...

Reusing style with mixins

mikkel250
I've been tinkering with computers since I was a teen. I'm currently pivoting from my current role as Tech Support manager to Full Stack Web Developer. I'm actively seeking employment in the field.
・3 min read

There are a few different ways to extend styles with Sass, some of which have been covered in this series already. We'll cover some new concepts by first going over each and how they behave in order to understand the new syntax and why it might be used.

include

The first way to extend a style is using a mixin and using @include to bring it into other styles:

// using @include
@mixin danger {
  background: red;
  color: white;
}

.btn-danger {
  @include danger(); // note parentheses even if no arguments are passed in
  padding: 2px;
}

.alert-danger {
  @include danger();
  width: 100%;
}

// compiles to CSS
.btn-danger {
  background: red;
  color: white;
  padding: 2px;
}

.alert-danger {
  background: red;
  color: white;
  width: 100%;
}

Note that the things that are common to both (defined in the mixin) are included in both CSS rules, which is not particularly DRY and could end up bloating your CSS file.

extend

The second way to is by using @extend. You can define the common elements in a 'parent' style rule and add specific tweaks as needed:

// using @extend
.danger {
  background: red;
  color: white;
}

.btn-danger {
  @extend .danger;
  padding: 2px;
}

.alert-danger {
  @extend .danger;
  width: 100%;
}

// compiles to CSS
.danger,
.btn-danger,
.alert-danger {
  background: red;
  color: white;
}
.btn-danger {
  padding: 2px;
}

.alert-danger {
  width: 100%;
}

This method works great, and results in much DRYer code and smaller CSS files. The problem with this method is if @extend is used in different places, and someone changes the danger style, it will affect the entire app wherever @extend was used, and this may not be immediately clear that would be the case, especially if the styles are spread out over different files and partials throughout the app.

Introducing: Placeholder

In order to deal with this potential problem with @extend, Sass has a way to let everyone working on the app know that a style is meant to be extended: placeholders.

// with placeholders
%danger {
  background: red;
  color: white;
}

.btn-danger {
  @extend %danger;
  padding: 2px;
}

.alert-danger {
  @extend %danger;
  width: 100%;
}

The compiled CSS looks the same as the previous example using @extend on a regular class, but it lets everyone know that danger is meant to be extended and to check before making changes. Using placeholders and extend are a great way to pass in style rules that don't require any variables.

There are some caveats to note when using @extend.
First, if there are multiple layers of nesting in your Sass (especially if each layer has multiple selectors in it), using @extend can cause the size of your CSS to blow up very quickly because nearly every permutation of each selector will be created in the compiled CSS, so keep an eye on it and consider breaking out classes into separate rules if this happens. The takeaway: be careful with nesting, and don't nest too deep, even if it means making your Sass file a bit longer, and a bit more work for you at the outset. The final product will have better performance and happier users.
Second, always use placeholders with @extend, even if it means having to create a separate class and bringing in @extend there, because this will avoid unintended changes later. I.e. if you wanted to create a parent .danger class, do it like so:

// with placeholders
%danger {
  background: red;
  color: white;
}

.danger {
  @extend %danger;
}

Discussion (0)