Categories
CSS

Sass Essentials 2018: Mixins

[Continued from SASS Essentials: Variables]

In the MIXINS folder are two interesting mixin-containing partial files. Mixins work like FUNCTIONS in other languages, allowing us to pass in values, process them in some way, and then return a value for use.

Because these are in a partial, however, I still need to import them. Here I am importing them near the top of the main style.scss file (along with my variables). The reason for this order is that a mixin or variable must be defined before it is used.

A Couple Simple Mixins

At the top of the mixins file are a few simple ones:

@mixin rounded {
  border-radius: 50%;
}

@mixin rounded-gentle{
  border-radius: 10px
}

@mixin center-block {
  margin: {
    left: auto;
    right: auto;
  }
}

@mixin center-image {
  display: block;
  @include center-block;
}

These work like “code shortcuts.” For example, in another sass file, I can reference the mixin(s) code like this:

.author-image {
  @include rounded;
  @include center-image;
}

This will compile into this:

  .author-image {
    border-radius: 50%;
    display: block;
    margin-left: auto;
    margin-right: auto;
  }

Passing Values to a Mixin

Like functions in any programming language, a SASS mixin can be passed values. Like in ES6, you can also set a default value in case the mixin is invoked without argument. Here is the syntax, and two examples:

@mixin circle($size:100px) {
  border-radius: 50%;
  width: $size;
  height: $size;
}

// use default value of 100px w and h
.generic img {
  @include circle();
}

// use passed value of 200px w and h
.profile img {
  @include circle(200px);
}

A Polygon Clip Path Mixin

The _shape.scss mixin file has the polygon-clip mixin: it takes in an $edge value, then outputs a clip-path on the side of the element specified. Basically, it creates a “pyramid effect” on one side of the box the mixin is invoked on.

In SASS, we write conditions with an @if syntax.

@mixin polygon-clip($edge){

  // POLYGON CLIP PATH COORDINATE SYNTAX
  //  0 0       = top left
  // 100% 0     = top right
  // 100% 100%  = bottom right
  // 0 100%     = bottom left

  @if $edge == right {
    clip-path: polygon(0 0, 100% 0, 95% 50%, 100% 100%, 0 100%);
  }

  @if $edge == left{
    clip-path: polygon(0 100%, 0 0, 100% 0, 95% 50%, 100% 100%);
  }

  @if $edge == top {
    clip-path: polygon(0 100%, 0 0, 100% 0, 95% 50%, 100% 100%);
  }

  @if $edge == bottom {
    clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 95%, 0 100%);
  }


}

With a mixin like this, I could then use it elsewhere like this:

.feature-image {
  @include polygon-clip(right); 
}

This will create a clip path on the right side of the .feature-image box.

A Musical Scale Typographic Mixin

The variable + mixin chain discussed here sets a typographic hierarchy based on notes from musical scales. The idea here is that we can make a typographic scale of font-sizes based on ratios from music or nature. We will use these ratios to create font-sizes in REMS and PX (the latter as a fallback for older browsers that don’t support REMs).

For more information, go to type-scale.com.

First, open up the typography partial inside the variables folder. Part of the code there looks like this (the sass comments explain which of two musical harmonies are used, along with the golden ratio from art theory and architecture).

$font__size-html: 16;   // pixels
$font__scale-multiple: 1.25; // Major Third
$font__scale-multiple: 1.414; // Augmented Fourth
$font__scale-multiple: 1.616; // Golden Ratio
$font__size-p: 1.25;      // rem

$font__size-h6: ($font__size-p / $font__scale-multiple);
$font__size-h5: $font__size-p;
$font__size-h4: $font__size-p * $font__scale-multiple;
$font__size-h3: $font__size-p * $font__scale-multiple  * $font__scale-multiple;
$font__size-h2: $font__size-p * $font__scale-multiple * $font__scale-multiple;
$font__size-h1: $font__size-p * $font__scale-multiple * $font__scale-multiple  * $font__scale-multiple;

In this example, the last multiple is the Golden Ratio, but if we comment out that line, the scale multiple will be the Augmented Fourth. (More values available at type-scale.com).

When we change the multiple, we change the ratio between steps in our typographic scale. In the example above, we’ve set the h5 element to be the size of the paragraph element. The h6 element is one step in the scale below that. The h4 is one step above; the h3 two steps above; the h2 three steps above; and the h1 is four steps above.

As of the time I’m writing htis, SASS does not have a way to write exponents, so the math above is a bit laborious. You could of course make it less so by “laddering” it like this:

$font__size-h5: $font__size-p;
$font__size-h6: $font__size_p / $font__scale-multiple;
$font__size-h4: $font__size_p * $font__scale-multiple;
$font__size-h3: $font__size-h4 * $font__scale-multiple;
$font__size-h2: $font__size-h3 * $font__scale-multiple;
$font__size-h1: $font__size-h2 * $font__scale-multiple;

Here’s a useful and simple mixin to have a px font-size fallback:

@mixin font-size($fs) {
  font-size: ($fs * $font__size-html) + px;
  font-size: $fs + rem;
}

What this will do is take in the passed value, then output the size first in PX then in REM units.

If you then look inside the TYPOGRAPHY partial in the TYPOGRAPHY folder (not the one in the VARIABLES folder), you’ll find code like this:


html {
  font-size: $font__size-html + px;
}

p {
  font-family: $font__body-copy;
  line-height: $line-height__p;
  @include font-size($font__size-p);
}

h1, h2, h3, h4, h5, h6 {
  font-family: $font__sans;
  margin-bottom: 0;
}

h2, h3 {
  color: lighten($color__rich-black, 20%);
}


h1 {
  @include font-size($font__size-h1);
}

h2 {
  @include font-size($font__size-h2);
}

h3 {
  @include font-size($font__size-h3);
}

h4 {
  @include font-size($font__size-h4);
}

h5 {
  @include font-size($font__size-h5);
}

h6 {
  @include font-size($font__size-h6);
}

With our heading styles, then, we take in the $font__size calculated for each in the variables section using the ratios derived from musical scales and then output those values like this:

h6 {
  font-size: 12px;
  font-size: .75rem
}