Yesterday, we modified our initial example applying Sass mixins to it. Today, we’re going to continue improving it by adding a couple more mixins that are very useful. It's a good practice to define themes for your style. You can define a series of standard elements, and control them dynamically using theme classes. This is easier to maintain, and it’s also great if you want to change the look of your site and don't want to go crazy changing a lot of files. There are a bunch of other good reasons, but let's see a simple example using plain CSS:

.theme-example .default-button.-danger {
  color: #b82601;
}
.theme-example .default-button.-main {
  background: #062f4f;
}

.theme-blue .default-button.-danger {
  color: red;
}
.theme-blue .default-button.-main {
  background: blue;
}

Let’s automate that. We can define optional parameters with its default value. We’re going to take advantage of that, so we define a mixin called theme. It receives five parameters. the name of the theme, the main color of the theme, the color background for headers (which will be the main color if none is defined), the danger color for buttons, and the secondary color of the theme (which will be a brighter version of the main color by default). Of course, you can modify all that to your preference. Once we have defined the parameters, we can interpolate the $name to create a parent class. Then, define all the common elements we want to style inside of it, like this:

@mixin theme($name, $color, $header: $color, $danger: $milano_red, $secondary: lighten($color, 15%)) {
  .#{$name} {
    .banner-wrapper {
      background-color: $header;
    }
    .default-button.-main {
      background-color: $color;
      &:hover {
        background-color: darken($color, 10%);
      }
    }
    .default-button.-danger {
      background-color: $danger;
      &:hover {
        background-color: darken($danger, 10%);
      }
    }
  }
}

Also, we are defining the hovers and backgrounds dynamically. So, we don't need those properties defined in our components anymore. Let's delete those extra lines from our components.

// components/_default-button.scss
.default-button {
  border-radius: 0.5rem;
  color: darkgray;
  cursor: pointer;
  font-size: 1.25rem;
  margin: 0.5rem auto;
  width: 15rem;
  padding: 0.5rem;
  text-align: center;
  transition: $default-transition;
  @include media("md") {
    margin: 0 0.5rem;
  }
}

// components/_banner-wrapper.scss
.banner-wrapper {
  box-sizing: border-box;
  height: 100vh;
  padding: 0 0.5rem;
}

Once we have our mixin ready and our components clean of extra code, we can use it like this:

@include theme(theme-example, $tarawera, $plum, $milano_red);
@include theme(theme-blue, blue, $tarawera);

Now, we can change our theme dynamically by adding the theme class to our body. If we add the class theme-example to the body the appearance is maintained, but look what happens if we change the class to theme-blue. Great!

The last mixin I want to show you is one of my favorites. External fonts can be annoying sometimes, even if you copy-paste the bullet proof snippet, you can write the wrong font name or delete part of one of the extensions, etc. However, don’t worry. Sass will facilitate this issue for us. First let’s create a fonts folder inside assets and add some fonts to it. Now we can see the code in plain css:

@font-face {
  font-family: "gothic";
  src: url("fonts/gothic.eot");
  src: url("fonts/gothic.eot?#iefix") format("embedded-opentype"), url("fonts/gothic.woff")
      format("woff"), url("fonts/gothic.ttf") format("truetype"), url("fonts/gothic.svg#gothic")
      format("svg");
  font-weight: normal;
  font-style: normal;
}

Another problem with this is that if we use more than one font we have to define the same code changing the name for each one. However, fonts have variations like: bold, italic, light, etc., and each variation has its own file. That means we could potentially be repeating the same code for a bunch of files for the same font. So, let’s modify this code into a mixin we can easily reuse. If we look closely, we can notice that some things are being repeated, like the font name, the font path and the value for font-weight and font-style. So these four are going to be our parameters.

@mixin font-face($font-name, $path: "fonts/", $weight: normal, $style: normal) {
}

Now we basically add the font-face code, but applying the parameters in its respective position, like this:

@mixin font-face($font-name, $path: "fonts/", $weight: normal, $style: normal) {
  @font-face {
    font-family: quote($font-name);
    src: url($path + $font-name + ".eot");
    src: url($path + $font-name + ".eot?#iefix") format("embedded-opentype"), url($path +
          $font-name + ".woff") format("woff"),
      url($path + $font-name + ".ttf") format("truetype"), url($path +
          $font-name + ".svg##{$font-name}") format("svg");
    font-weight: $weight;
    font-style: $style;
  }
}

Notice we’re using a sass method called quote, which basically adds quotes to a string, or returns the same string if it isn't quoted, to make sure the font name is always correct. After that we just have to apply the mixin in _elements.scss and add the font name to our default-font variable:

// assets/_elements.scss
@include font-face("gothic");

// assets/_variables.scss
$default-font: gothic, helvetica, arial, sans-serif;

Now our fonts are updated! Wait. While this is an improvement, because we just need to use one line of code for each font, it’s still annoying to do the same process several times. So, lets automate our mixin a little more. First we change $font-name to $fonts, then we define a map with all our fonts.

$fonts: (
  "gothic",
  "gothicb",
  "gothicbi",
  "gothici"
);

We’re going to use @each, and we move the font-face inside of it.

@mixin font-face($fonts, $path: 'fonts/', $weight: normal, $style: normal) {
  @each $font in $fonts {
    @font-face {
      font-family: quote($font);
      src: url( $path + $font + '.eot');
      src: url( $path + $font + '.eot?#iefix')  format('embedded-opentype'),
           url( $path + $font + '.woff') format('woff'),
           url( $path + $font + '.ttf')  format('truetype'),
           url( $path + $font + '.svg##{$font}')  format('svg');
      font-weight: $weight;
      font-style: $style;
    }
  }
}

Basically, we iterate through our fonts map, and define a font-face for each font contained there. Now we modify our mixin application, and instead of the name, we pass our map as argument. Like this:

@include font-face($fonts);

Our fonts are applied, if we check our application.css we can look all the font-faces our mixin defined:

Great! We learned a lot of things: complex mixins, conditionals, maps, and more Sass methods. All of these features are incredibly useful, and can improve our workflow a lot. It's up to you to find new ways to use them!

Sass has more tricks up its sleeve, so stay tuned to see some of them in the next video. See ya!