Codementor Events

Functional Sassy CSS (SCSS)

Published Mar 01, 2017
Functional Sassy CSS (SCSS)

For me, CSS or SCSS are means to greater ends - they allow me to style elements. However, my passion on the front-end mainly lie in JavaScript and the puzzles we get to solve creatively. So when I started playing around with loops and conditional statements in Sassy CSS (SCSS), I was super excited to see that SCSS can also be a fun way to solve styling issues with more traditional programming techniques.

The project I had was to create a carrot/triangle pointing to the right. So I started to search the Internet for solution. I came across this cool post about using some css tricks to create a css-only arrow.


  .arrow-right {
  	width: 0;
  	height: 0;
  	border-top: 20px solid transparent;
  	border-bottom: 20px solid transparent;

  	border-left: 20px solid green;
  }

OK, great! So now, maybe I want to have another arrow pointing down as well. We can do this like so:


  .arrow-down {
    width: 0;
    height: 0;
    border-left: 20px solid transparent;
    border-right: 20px solid transparent;

    border-top: 20px solid green;
  }

Also, maybe an arrow left and up just to complete the picture.


  .arrow-left {
    width: 0;
    height: 0;
    border-top: 20px solid transparent;
    border-bottom: 20px solid transparent;

    border-right: 20px solid green;
  }

  .arrow-up {
  	width: 0;
  	height: 0;
  	border-left: 20px solid transparent;
  	border-right: 20px solid transparent;

  	border-bottom: 20px solid green;
  }

It's easy to see the pattern here. So what if I wanted a smaller arrow (say 10px), that would mean creating all of this code over again and replacing the 20px with a 10px. If I were to do that, I would be violating the DRY principle.

SCSS functions to the rescue!

This would be the final code that would be able to generate arrows in all directions and whatever sizes we choose. In this example 5, 10 and 20px.


  $sizes: small 5px, medium 10px, large 20px;
  $directions: up right down left;

  @mixin carrot($size, $color, $direction) {
    width: 0;
    height: 0;
    border: $size solid transparent;
    @if $direction == 'down' { border-top: $size solid $color; }
    @if $direction == 'up' { border-bottom: $size solid $color; }
    @if $direction == 'left' { border-right: $size solid $color; }
    @if $direction == 'right' { border-left: $size solid $color; }
}

  @each $size in $sizes {
    @each $direction in $directions {
        .carrot-#{$direction}-#{nth($size, 1)} {
            @include carrot(nth($size,2), #fff, $direction);
        }
    }
  }

First off, we set up our two variables $sizes and $directions. Since SCSS doesn't have the direct concept of arrays, we will use what is called a list. The values are comma separated — you can think of what is in between the commas as the array portion. So if we look over $sizes, we'll get the first value as [small, 5px] and can access each piece using the nth function.


$sizes: small 5px, medium 10px, large 20px;

@each $size in $sizes {
  nth(($size, 1));
}

This would find such loop in the $sizes list and grab the first term that are small, medium, and large. Lists start with 1 as opposed to 0 with arrays.

The next piece is a @mixin, which is what we use to create a SCSS function. Inside the @mixin, we have 4 conditionals, which are the only parts of the border that change according to each triangle's direction. That's pretty much it for the @mixin.

Next it's use.

Like we showed above, we will use loops to generate the classes that will define the arrows. But more specifically, we will use two loops to create the classes. First, loop over the sizes, and then from each size and name we specify, we can create the 4 directional arrows.

That's it!

Super simple SCSS functions, to abstract repetition. Here is a working example of it. If you click 'View Compiled' you can see the CSS that is generated from the code.

Discover and read more posts from Sten Muchow
get started
post commentsBe the first to share your opinion
sheriffderek
7 years ago

SVG!

Show more replies