5 SCSS Mixins to check out!
Tags: webdev, css, html, sass
Published: 2021-03-07 00:22:26


`Hello World!` Today's article is about one of the primary motivations for using SASS - mixins. I talk about what mixins are, why you should use them, and share 5 of my favourite mixins I've written (_and a bonus one at the end too_ 😁).

### Table of Contents

1. [What, Why, How?](#introduction)
2. [Media Queries](#media-queries)
3. [Positioning](#position)
4. [Fonts](#fonts)
5. [Transitions](#transition)
6. [Pseudo Elements](#pseudo)
7. [Z-index](#z-index)
8. [Conclusion](#conclusion)

---

# The What, Why & How of Mixins? <a name="introduction"></a>

A SASS - Mixin brings into practice one of software development's primary principles - DRY (Don't Repeat Yourself), by encapsulating CSS style declarations into a code block and allowing us to reuse them throughout our site. Mixins not only take care of redundancy in style sheets but also significantly speed up your work flow by reducing the number of lines you have to type.

Now that I've convinced you of why you should use mixins, let's see how we can create mixins.
Mixins can be defined using the `@mixin` rule. The general syntax for creating a mixin is as follows:

```SCSS
@mixin <name>(<arguments...>) {
    // mixin content
}
```

After being declared, mixins can be easily integrated into our stylesheets using the `@include` rule.

```SCSS
@include <name>(<arguments...>)
```

With the What, Why & How out of the way, here are 5 of my favourite mixins (and a bonus at the end too :)).

# Media Queries <a name="media-queries"></a>

With up to half of all web traffic coming from mobile devices, it has become essential for websites to become responsive, however the syntax for vanilla CSS media queries is still clunky. My SCSS mixin aims to ease some of the pain.

You can define custom `$breakpoints` or pass numerical values. Furthermore, additional options can be added using the `$and` parameter.

```SCSS
// Custom Breakpoints
$breakpoints: (
  sm: 576px,
  md: 768px,
  xl: 1200px,
);
// Media-Query Mixin
@mixin media(
    $from: false,
    $until: false,
    $and: false,
    $media-type: all,
) {
    $min-width: 0;
    $max-width: 0;
    $query: "";

    //FROM: this breakpoint (inclusive)
    @if $from {
        @if type-of($from) == number {
            $min-width: $from;
        } @else {
            $min-width: map-get($breakpoints, $from);
        }
    }

    //UNTIL: this breakpoint (exclusive)
    @if $until {
        @if type-of($until) == number {
            $max-width: $until - 1px;
        } @else {
            $max-width: map-get($breakpoints, $until) - 1px;
        }
    }

    @if $min-width != 0 {
        $query: "#{$query} and (min-width: #{$min-width})";
    }
    @if $max-width != 0 {
        $query: "#{$query} and (max-width: #{$max-width})";
    }
    @if $and {
        $query: "#{$query} and (#{$and})";
    }

    @if ($media-type == "all" and $query != "") {
        $media-type: "";
        $query: str-slice(unquote($query), 6);
    }

    @media #{$media-type + $query} {
        @content;
    }
}
```

### Usage:

SCSS:

```SCSS
.foo-bar {
    width: 50%;
    @include media($from: "sm", $until: 900px, $and:"orientation: landscape"){
        width: 100%;
    }
}
```

CSS:

```CSS
.foo-bar {
    width: 50%;
}
@media (min-width: 576px) and (max-width: 899px) and (orientation: landscape) {
    .foo-bar {
        width: 100%;
    }
}
```

> **BONUS**: If you have a media-query being used throughout your style sheet, create nested mixins to further streamline your workflow.

```SCSS
@mixin sm-md{
    @include media($from: "sm", $until: "md"){
        @content
    }
}
```

# Positioning <a name="position"></a>

This mixin is a massive time-saver when you want to position several elements. The values are provided in the order `top right bottom left`. Additionally, values such as `auto`, `inherit`, and `initial` are also supported.

Note: You can force a `0px` offset by passing `f0` to the mixin.

```SCSS
@mixin pos($type, $args: 0 0 0 0) {
    position: $type;
    $offsets: top right bottom left;
    @if length($args) == 2 or length($args) == 4 {
        @if length($args) == 2 {
            $args: join($args, $args);
        }
        @each $offset in $offsets {
            $offsetVal: nth($args, index($offsets, $offset));
            #{$offset}: validOffset($offsetVal);
        }
    } @else {
        @warn "Invalid number of arguments. (Must be either 2 or 4).";
    }
}

@function validOffset($value) {
    @if type-of($value) == number {
        @if ($value != 0) {
            @return $value;
        } @else {
            @return null;
        }
    } @else if str-slice($value, 1, 1) == "f" {
        @return str-slice($value, 2);
    } @else if index(auto initial inherit, $value) {
        @return $value;
    } @else {
        @warn "Invalid offset value.";
        @return null;
    }
}

@mixin abs($args: 0 0 0 0) {
    @include pos(absolute, $args);
}
@mixin rel($args: 0 0 0 0) {
    @include pos(relative, $args);
}
@mixin fix($args: 0 0 0 0) {
    @include pos(fixed, $args);
}
@mixin sticky($args: 0 0 0 0) {
    @include pos(sticky, $args);
}
```

### Usage

SCSS:

```SCSS
.foo-bar{
    @include rel(0 f0 auto 50%)
}
```

CSS:

```CSS
.foo-bar {
    position: relative;
    right: 0;
    bottom: auto;
    left: 50%;
}
```

# Fonts <a name="fonts"></a>

This mixin provides a short hand for setting fonts, their fallbacks and style properties (font-family, size, weight, color, style and line-height). The mixin can be easily modified to all fallback support for sans-serif or any other font category.

> ⚠️ Be sure to include the fonts using the `@font-face` rule.

```SCSS
@mixin font-serif($name, $size: false, $weight: false, $color: false, $style: false, $lh: false) {
    font-family: $name, "Times New Roman", Times, serif;
    @if $size {font-size: $size};
    @if $weight {font-weight: $weight};
    @if $color {color: $color};
    @if $style {font-style: $style;}
    @if $lh {line-height: $lh;}
}
```

### Usage

SCSS:

```SCSS
.foo-bar{
    @include font-serif("Noto Serif", 1.2rem, 700, #181818)
}
```

CSS:

```CSS
.foo-bar {
    font-family: "Noto Serif", "Times New Roman", Times, serif;
    font-size: 1.2rem;
    font-weight: 700;
    color: #181818;
}
```

> BONUS: Use the <a href="https://github.com/twbs/rfs">RFS Engine</a> to set the font-sizes and achieve reponsive text; Example: `@include font-size($size)`.

# Transitions <a name="transition"></a>

Assign multiple transitions using this mixin. The transitions for which `transition-duration`, `transition-delay` and `transition-timing-function` is not defined inherit it from the last defined duration,delay and timing function.

```SCSS
@mixin transition($prop, $time, $easing: ease-in, $delay: 0s) {
    $transition: ();
    @for $i from 1 through length($prop) {
        @for $j from 0 to (length($prop)) - (length($time)) {
            $time: join($time, nth($time, -1));
        }
        @for $j from 0 to (length($prop)) - (length($easing)) {
            $easing: join($easing, nth($easing, -1));
        }
        @for $j from 0 to (length($prop)) - (length($delay)) {
            $delay: join($delay, nth($delay, -1));
        }

        $transition: append(
            $transition,
            (nth($prop, $i) nth($time, $i) nth($easing, $i) nth($delay, $i)),
            $separator: comma
        );
    }
    transition: $transition;
}
```

### Usage

SCSS:

```SCSS
.foo-bar{
    @include transition(width opacity transform, 0.3s 0.4s, linear, 0.1s)
}
```

CSS:

```CSS
.foo-bar {
    transition: width 0.3s linear 0.1s, opacity 0.4s linear 0.1s, transform 0.4s linear 0.1s;
}
```

# Pseudo-Elements <a name="pseudo"></a>

While pseudo-elements are useful for creating masking effects on text and images, they include a lot of code repetition. Let's reduce the number of lines of code with this mixin.

```SCSS
@mixin pseudo($display: block, $pos: absolute, $content: '', $width: 100%, $height: 100%){
    content: $content;
    display: $display;
    position: $pos;
    width: $width;
    height: $height;
}
```

### Usage:

SCSS:

```SCSS
.foo-bar::before{
    @include pseudo($width: 100px)
}
```

CSS:

```CSS
.foo-bar::before {
    content: "";
    display: block;
    position: absolute;
    width: 100px;
    height: 100%;
}
```

# Z-index <a name="z-index"></a>
While not technically a mixin, this function allows you to define multi-level z-indexes in one place and prevents spaghetti code like `z-index: 999`.

```SCSS
$z-indices: (
    "menu": (
        "items": 2,
        "social": 3,
    ),
    "main-content": 1,
    "footer": -1,
);

@function ind($element, $sub-element: false){
    $index: map-get($z-indices, $element);
    @if $sub-element{ $index: map-get($index, $sub-element); }
    
    @return $index;
}
```
### Usage
SCSS:
```SCSS
.menu{
    .items {
        z-index: ind(menu, items);
    }
}
.footer{
    z-index: ind(footer);
}
```
CSS:
```CSS
.menu .items {
    z-index: 2;
}

.footer {
    z-index: -1;
}
```
---

## Conclusion <a name="conclusion"></a>
These are some of the mixins I created for use when working on my <a target="_blank" href="https://nidhishs.github.io">Portfolio Website</a>. I hope some of these mixins prove to be useful to you, and inspire you to create some of your own. As a rule of thumb, if you are repeating yourself, consider creating a mixin.


Drop a ❤️. Your encouragement keeps me going. Let me know some of your favorite mixins in the comments.
Any suggestions or criticism for improvement are, of course, welcome 😄.

### References:
1. <a target="_blank" href="https://sass-lang.com/documentation">SASS documentation</a>
2. <a target="_blank" href="https://github.com/twbs/rfs">Responsive Font Sizes Engine</a>