Style Your CSS With Sass!

Style Your CSS With Sass!

Nowadays, CSS is a complex toolbox that not all web developers are willing to embrace (even though it’s awesome).  And we all know that any web app can quickly be overwhelmed with styles and classes, making it even harder to keep track of what selectors are overriding what styles, transitioning from “Cascade Style Sheets” to “Cascade Style Nightmare”.

Luckily, there are tools that help us write CSS in a more compact and declarative manner.

Particularly, we’ll be looking at SASS (Syntactically Awesome Style Sheets), a preprocessor (one more step in the buildchain) that transpiles code from one of its 2 different syntaxes to CSS. (transpiling refers to compiling code from one language to another, we’ll be using that word pretty often!)

In this article, we’ll be viewing examples written in SCSS (the newer of the syntaxes). It’s worth mentioning that each and every example has a direct equivalent in the older syntax.  Also, it lets you write standard CSS, so it’s not a completely different style sheet language to learn, which could be seen as a drawback.

You can think of it as CSS with Superpowers.

In the end of this article there'll be a live demo showing what's possible to do!

Let’s have a look at some of these features:

Selector Nesting

Let’s suppose we need to apply some styles to containers inside containers, but we don’t want to create classes because we won’t repeat these styles.

This is the standard solution using CSS:

body {
    display: flex;
    align-items: center;
    justify-content: center;
  }

  body > div {
     width: 60%;
     box-shadow: 0px 0px 71px 10px rgba(0, 0, 0, 0.75);
     background-color: white;
  }

  body > div > div {
    width: 80%;
    background-color: red;
  }

  body > div > span {
    width: 20%;
    background-color: yellow;
  }

A little redundant, isn’t it?

Let’s see what Sass proposes:

body {
  display: flex;
  align-items: center;
  justify-content: center;

  > div {
    width: 60 vh;
    box-shadow: 0px 0px 71px 10px rgba(0, 0, 0, 0.75);
    background-color: white;


   > div {
      width: 80%;
      background-color: red;
   }
   > span {
     width: 20%;
     background-color: yellow;
   }
 }
}

Pretty cool, right? This can help a lot when there’s a bunch of different nested styles coming into play.

Another cool thing is that not only this applies for immediate css children, it can apply for whatever selector rule you want to nest.
For example, you can nest classes!

.container { 	
  background:red; 
  &.desc { 
    background:blue; 
  }
  &:hover {
    background: violet;
  }
  &-special{
    background: green;
  }
}

The & works as a parent element placeholder!

This transpiles to:

.container { background: red; } 
.container.desc { background: blue; }
.container:hover { background: violet; }
.container-special { background: green; }

This way of writing classes helps following conventions like BEM. Keeping styles organized and legible.

Functions

So, did you know that there's no way to generate a random number using common CSS?

I came across this problem wanting to make some divs move in a random direction on a small project.

Well, SCSS saves the day again! This time with some native functions!.

There is actually a bunch of Sass native functions in the docs.

Here’s is an example using random() to... guess what? Get a random width in px.

div {
  width: random() + px;
  background-color: red;
}

Ok, so everything’s good with Sass native functions, but what if i want to create my own? Well... of course you can! Here's an example.

@function randomRange($min, $max) {
  $rand: random();
  $randomNum: $min + floor($rand * (($max - $min) + 1));
  @return $randomNum;
}

Surprisingly, Sass doesn’t come with a ranged random function natively, so I just created my own ^^.

As you may guess, you can get infinitely more creative with functions in Sass, giving you the possibility to put out some crazy style calculations!

DISCLAIMER:

Sass is a preprocessor, this means that the random function will be calculated just once (when it transpiles to css). If we needed to constantly change the width px in runtime, we would need to use Javascript.

Lists

This is one of the most useful features. Basically, it means that you can create a number of calculated rules in one go! Even animations!

Here's an example of 4 animations created in one go, using the ranged random function created previously.

$particle-range: 600%;

$particle-types:
 positive-x translate($particle-range, randomNum(-200,200) + 0%),
 negative-x translate(-$particle-range, randomNum(-200,200) + 0%),
 positive-y translate(randomNum(-200,200) + 0%, $particle-range),
 negative-y translate(randomNum(-200,200) + 0%, -$particle-range);

@each $type, $translate in  $particle-types {

 @keyframes particle-#{$type} {

   0%  {
     width: 0%;
     transform: #{$translate};
   }

   20% {
     width: 3%;
     transform: #{$translate};
   }

   100% {
     width: 0%;
     transform: translate(0, 0);
   }
 }
}

Whoa! That’s a tricky block of code to read!

To explain it briefly, $particle-types is a list of tuples, with the first element ($type) being the name of the type of the animation and the second element ($translate) being the value of the transform animation.

We use #{...} to convert any sass expression to string, so $translate and $type are not taken as identifiers.

Then, with @each, we iterate through the list defining 4 different unique animations.
This is the ending result after transpiling:

@keyframes particle-positive-x {
  0% {
    width: 0%;
    transform: translate(600%, 59%); }
  20% {
    width: 3%;
    transform: translate(600%, 59%); }
  100% {
    width: 0%;
    transform: translate(0, 0); } 
}

@keyframes particle-negative-x {
  0% {
    width: 0%;
    transform: translate(-600%, -191%); }
  20% {
    width: 3%;
    transform: translate(-600%, -191%); }
  100% {
    width: 0%;
    transform: translate(0, 0); } 
}

@keyframes particle-positive-y {
  0% {
    width: 0%;
    transform: translate(-74%, 600%); }
  20% {
    width: 3%;
    transform: translate(-74%, 600%); }
  100% {
    width: 0%;
    transform: translate(0, 0); } }

@keyframes particle-negative-y {
  0% {
    width: 0%;
    transform: translate(176%, -600%); }
  20% {
    width: 3%;
    transform: translate(176%, -600%); }
  100% {
    width: 0%;
    transform: translate(0, 0); } 
}

Now I’ll show you another example of Lists, this time, creating n-number of classes, applying the 4 animations previously created.

delay: 0;

$particle-clases:
 particle-positive-x,
 particle-positive-y,
 particle-negative-x,
 particle-negative-y,
 particle-positive-x,
 particle-positive-y,
 particle-negative-x,
 particle-negative-y,
 particle-positive-x,
 particle-positive-y,
 particle-negative-x,
 particle-negative-y;

@each $particle-class in $particle-clases {
 .p#{$delay} {
   position: absolute;
   background: radial-gradient(circle, rgba(6,4,138,1) 27%, rgba(139,0,252,1) 77%);
   animation:  #{$particle-class} 5s ease-in-out infinite;
   animation-delay: #{$delay}s;
 }
 $delay: $delay + 1;
}

To explain it briefly, we create 12 css classes: p0, p1, …  p11. In which we apply a specific animation depending on the iteration number. Also, each class has a specific animation delay, that we increment per iteration.

The delay is to display an effect in which each class starts its animation after the other.

Here is the transpiled code:

.p0 {
  position: absolute;
  background: radial-gradient(circle, #06048a 27%, #8b00fc 77%);
  animation: particle-positive-x 5s ease-in-out infinite;
  animation-delay: 0s; 
}

.p1 {
  position: absolute;
  background: radial-gradient(circle, #06048a 27%, #8b00fc 77%);
  animation: particle-positive-y 5s ease-in-out infinite;
  animation-delay: 1s; 
}


/* clases from p2 to p10*/

.p11 {
  position: absolute;
  background: radial-gradient(circle, #06048a 27%, #8b00fc 77%);
  animation: particle-negative-y 5s ease-in-out infinite;
  animation-delay: 11s; 
}

Conclusion and live demo!

To wrap this up, Sass comes with lots of features that can make your life easier. Here we’ve had a look at the basics, and then in the docs you can look for a bunch of cooler features like modules, mixins and more!
Here's an integrated demo of the features we’ve seen: