DEV Community

loading...

5 SCSS Mixins to check out!

nidhishs profile image Nidhish Shah ・5 min read

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?
  2. Media Queries
  3. Positioning
  4. Fonts
  5. Transitions
  6. Pseudo Elements
  7. Z-index
  8. Conclusion

The What, Why & How of Mixins?

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:

@mixin <name>(<arguments...>) {
    // mixin content
}
Enter fullscreen mode Exit fullscreen mode

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

@include <name>(<arguments...>)
Enter fullscreen mode Exit fullscreen mode

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

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.

// 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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Usage:

SCSS:

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

CSS:

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

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

@mixin sm-md{
    @include media($from: "sm", $until: "md"){
        @content
    }
}
Enter fullscreen mode Exit fullscreen mode

Positioning

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.

@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);
}
Enter fullscreen mode Exit fullscreen mode

Usage

SCSS:

.foo-bar{
    @include rel(0 f0 auto 50%)
}
Enter fullscreen mode Exit fullscreen mode

CSS:

.foo-bar {
    position: relative;
    right: 0;
    bottom: auto;
    left: 50%;
}
Enter fullscreen mode Exit fullscreen mode

Fonts

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.

@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;}
}
Enter fullscreen mode Exit fullscreen mode

Usage

SCSS:

.foo-bar{
    @include font-serif("Noto Serif", 1.2rem, 700, #181818)
}
Enter fullscreen mode Exit fullscreen mode

CSS:

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

BONUS: Use the RFS Engine to set the font-sizes and achieve reponsive text; Example: @include font-size($size).

Transitions

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.

@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;
}
Enter fullscreen mode Exit fullscreen mode

Usage

SCSS:

.foo-bar{
    @include transition(width opacity transform, 0.3s 0.4s, linear, 0.1s)
}
Enter fullscreen mode Exit fullscreen mode

CSS:

.foo-bar {
    transition: width 0.3s linear 0.1s, opacity 0.4s linear 0.1s, transform 0.4s linear 0.1s;
}
Enter fullscreen mode Exit fullscreen mode

Pseudo-Elements

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.

@mixin pseudo($display: block, $pos: absolute, $content: '', $width: 100%, $height: 100%){
    content: $content;
    display: $display;
    position: $pos;
    width: $width;
    height: $height;
}
Enter fullscreen mode Exit fullscreen mode

Usage:

SCSS:

.foo-bar::before{
    @include pseudo($width: 100px)
}
Enter fullscreen mode Exit fullscreen mode

CSS:

.foo-bar::before {
    content: "";
    display: block;
    position: absolute;
    width: 100px;
    height: 100%;
}
Enter fullscreen mode Exit fullscreen mode

Z-index

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.

$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;
}
Enter fullscreen mode Exit fullscreen mode

Usage

SCSS:

.menu{
    .items {
        z-index: ind(menu, items);
    }
}
.footer{
    z-index: ind(footer);
}
Enter fullscreen mode Exit fullscreen mode

CSS:

.menu .items {
    z-index: 2;
}

.footer {
    z-index: -1;
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

These are some of the mixins I created for use when working on my Portfolio Website. 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. SASS documentation
  2. Responsive Font Sizes Engine

Discussion (0)

pic
Editor guide