Andy from Webcrunch

Subscribe for email updates:

A Deeper Look at Sass and Why You Should Be Using It
Portrait of Andy Leverenz
Andy Leverenz

January 13, 2016

Last updated November 5, 2023

A Deeper Look at Sass and Why You Should Be Using It

Sass is a not so new CSS language that hit the web design/development world by storm several years ago. Developers were wanting a less repetitive solution for writing more functional CSS. The organization, optimization, and overall ease-of-use were the driving forces behind the language. At the time of this post, Sass stands in at the top CSS-based language in the industry. If you haven't tried Sass or Less by now you are certainly missing out. Hopefully, this post will help you see why it's so powerful as well as popular.

What is Sass?

Sass stands for Syntactically Awesome Stylesheets. You can think of it as CSS on steroids. Sass allows you to write less code but still generate the same code you would if you were writing vanilla CSS. You are still writing CSS, but writing less and letting a compiler handle all the heavy lifting.

Sass at its core can't run on a basic web server. It's responsible for the generation of CSS via compilation. When Sass is compiled, depending on the tools you use, you can format your CSS however you like. When I was introduced to Sass I didn't see the value in learning a new language to write the same code I could already write. I finally took the time (very little) to get more familiar with Sass and I'm happy to report I'll never write regular ole' CSS again. When you start to see the advantage of the language you'll be hooked, I promise!

Several tools exist which provide support for Sass compilation among many other features. Some tools are GUIs (graphical user interfaces) while others are run via command line with task runners such as Grunt or Gulp.

Some popular GUI-based apps are:

All of these solutions work flawlessly with Sass. In the end, you'll need to decide what works best for your situation. I personally use Codekit when working on a project that is completely handled by myself and Gulp when working with a group of designers and developers on particular projects. I can tell you from experience that it pays to learn at least one of the task running languages as I've mentioned prior. Chances are any Github repo or open source project you download utilizes one and to get started, you need to know the basics. If you're interested in learning more about Gulp you should check out this post I wrote on it for an overview.

Sass Syntax

Sass comes in two flavors. I won't be writing both on this blog post because I personally only use one. One flavor is much like the CSS you are used to. This version features the curly braces while the other relies on indentation and whitespace. While the second flavor is certainly cleaner, I have found that it's a little more complicated if you get your indenting wrong. As always, in the end, use whichever method you prefer. Just remember to name your Sass files accordingly. The first flavor (my preferred style) has the file extension .scss whereas the other flavor has the .sass file extension.

Key Features

There are many reasons to write CSS using Sass. My favorite and probably many other people's favorite reasons are listed below. This language can be the simplest one you ever use or get very complex depending on your needs. You can write dynamic CSS if you really wanted which is what makes it so much more powerful than regular CSS alone.

Variables

Variables are without a doubt crucial to my Sass workflow. Remembering HEX or RGB color codes is a royal pain sometimes so variables can save you valuable time there. The same goes for font sizes or font family names. Defining a variable is done like this:

 $primary-color: #000000;
 $primary-font: Helvetica, sans-serif;

 #myDiv {
   color: $primary-color;
   font-family: $primary-font;
 }

Here I defined a variable called primary-color and primary-font by using a dollar sign in front of each followed by a colon and the actual value I want to use when my CSS is compiled. After defining the variables, I applied to the my element like I normally would with CSS. Rather than remembering or writing the color code over and over I can use an easy to remember variable to make things easier to remember.

Chances are your project will have a lot of variables. Defining these upfront allows you to create a more consistent look and feel across your website or app. We've all probably experienced having way too many different shades of a color on our websites because we were too lazy to copy and paste the same colors over and over. Sass helps a lot in this department and is only scratching the surface with what you can do with variables.

I tend to use variables for colors, font-sizes, font-weights, font-families, and much much more. The list is virtually endless.

Nesting

Probably the second most useful feature in Sass is nesting. Nesting allows you to sequentially write CSS that will compile into what would normally be really long declarations. To better understand what I mean check out the following code.

With traditional CSS you may want to select a specific element within the DOM (Document Object Model) using a selector like this:

#header ul li .first {
  padding-left: 0;
}

With Sass you can take advantage of nesting by selecting things a little more directly without needing the trail of ancestors in the full selection path:

 #header {
   .first {
     padding-left:0;
   }
 }

The Sass code above would compile into the traditional CSS I wrote prior to this. While it may seem a little cumbersome, nesting will save you so much more time by inheriting the DRY approach within your code. DRY stands for Don't Repeat Yourself and is the essence of the language.

Rather than writing:

 #header ul li .second {
   padding-left: 20px;
 }

You could continue where we left off before and write this with Sass:

 #header {
   .first {
     padding-left:0;
   }
   .second {
     padding-left: 20px;
   }
 }

Going one step further you could introduce variables for the values we assigned:

$pad: 20px;
$nopad: 0px;

#header {
    .first {
      padding-left: $nopad;
    }
    .second {
      padding-left: $pad;
    }
}

While nesting is a time-saver, it can sometimes get out of hand. I would suggest not nesting more than three levels deep. For the sake of readability and overall consistent code, you'll want to keep this standard throughout all of your styles. Don't feel like you have to nest your Sass code either. If you want to define some standard CSS then go for it. It will output with the rest of your Sass in the same manner.

It’s also worth mentioning that when you add a class or id to an HTML element you’ll want to adopt some sort of consistent naming convention. There is a lot of insight on this topic when it comes to writing CSS. A large number of ways exist such as SMACSS, BEM, and OOCSS just to name a few. You don’t have to adopt any of these conventions. Having your own style might be a better fit. The idea is to just make the naming convention consistent. This is especially true when multiple people are working on the project.

Partials

Another neat part about working with Sass is the ability to break apart groups of code into more organized chunks. These chunks(partials) are pieced out into separate smaller files which later get imported into a master file.

You can think of partials as a more modular approach to styling your website or application. Breaking things up takes a lot less time to find within your project directory. The larger your project becomes the harder it is to stay organized. Luckily, partials exist to help deviate this.

Creating a partial is easy and fairly straightforward. Say for instance you have all of your Sass in a folder called scss within your root directory.

css/
  style.css
scss/
  styles.scss

As you can see, in the folder structure above, there isn't a lot going on. We have one Sass file which is being compiled into a CSS file within the css folder. We want all of our Sass to compile into the same file which is style.css in this case.

Creating a Partial

To create a partial, you create a new file and prefix it with an underscore character. Doing this tells Sass not to compile the file directly. We don't want any partial to compile into a new file but rather compile down into our style.css file like all of the other code. For example, to make this work I'll create a fictional file called _reset.scss within the scss folder.

css/
  style.css
scss/
  styles.scss
  _reset.scss

To get the Sass code within the _reset.scss file to compile into our main style.css file we need to make use of the @import directive available to us. I'll discuss how this works next.

Imports

Since we want all of our CSS to end up in the same place we need to make use of the @import directive within our main styles.scss file. Think of this file the master Sass file that we will tell our compiler to look for when working its magic. Any new partials we create will get imported to the styles.scss file in whatever order we choose.

In the previous section, I created a new fictional file called _reset.scss.
The example contents are as follows:

/* _reset.scss */

html,
body,
ul,
ol {
  margin: 0;
  padding: 0;
}

To make use of the @import directive we need to declare an import in our styles.scss file like so:

/* styles.scss */

@import 'reset';

body {
  font-family: Helvetica, sans-serif;
  background: #f8f8f8;
}

Notice how when using the @import directive I didn't include the file suffix or the underscore character the _reset.scss the filename is prefixed with. Sass is smart enough to find the file and import it directly without those additional details. Pretty cool stuff.

It's worth noting that the order of imports matters. The styles.scss file will be compiled in the order that you author it. So in this case, all of our code within _reset.scss will output before any contents of the styles.scss file when it makes it to the master style.css file.

Hopefully this process made a little sense. If not be sure to let me know in the comments below.

Partials are crucial when scaling your application. It may seem counterintuitive to create a bunch of new files that get imported back into one in the end, but doing this will save you the trouble for having to hunt for code later on. If you are accustomed to traditional CSS you can probably relate as your CSS file grows it becomes harder and harder to reference as time goes on.

It goes without saying that the name of the partial file being imported is the main clue as to what code is being imported. You can add comments to help remind yourself what each partial entails as well. Some compilers are even smart enough to remove comments when you compile your Sass for production based code if you so desire.

Mixins

Mixins are amazing. If you ever find yourself repeating CSS across multiple elements of your application then I invite you to harness the power of mixins.

A mixin lets you make groups of CSS declarations that you want to reuse throughout your site. Ever get tired of writing CSS3 vendor prefixes? Mixins can take care of that for you.

If you’ve ever worked with JavaScript, mixins work a lot like functions. Functions are available to use wherever you so desire and you can use them an unlimited number of times. Data can be passed through the function(mixin) to get the desired result you’re looking for. A better way to illustrate my point is by example. Suppose we created another partial called _mixins.scss which would make our new project structure look like this:

css/
  style.css
scss/
  styles.scss 
  _reset.scss
  _mixins.scss

Inside the the styles.scss file I have made sure to import the _mixins.scss file:

/* styles.scss */

@import 'reset';
@import 'mixins';

body {
  font-family: Helvetica, sans-serif;
  background: #f8f8f8;
}

With everything set up, we can write a new mixin to use throughout our application. A good way to illustrate this is through the border-radius property within CSS3. Currently, you need to supply vendor prefixes to make this work across all browsers:

/* _mixins.scss */

@mixin border-radius($radius) {
    -webkit-border-radius: $radius;
       -moz-border-radius: $radius;
        -ms-border-radius: $radius;
            border-radius: $radius;
}

Our mixin is declared by writing @mixin and then giving it a name. In this case, since we are working with border-radius, it makes sense just to call it border-radius though you can name these whatever you prefer.

Within the mixin, we defined a variable called $radius which acts as an argument you can define later when we make use of the mixin throughout our application. The value is the only thing that changes in this case. The value once passed through the mixin gets assigned to each area with the $radius variable in place. You can have as many arguments as you like within a mixin. For the sake of brevity, I am keeping it simple.

At this point, our mixin is useless until we @include it on an element. For example's sake, I’ll add our mixin declaration to a div with the class of container within our styles.scss a file like so.

/* styles.scss */

@import 'reset';
@import 'mixins';

body {
  font-family: Helvetica, sans-serif;
  background: #f8f8f8;
}

/* Adding our border-radius mixin */
.container {
    @include border-radius(5px);
}

If all goes well our div with the class of .container should have a border-radius of 5px that is visible in most modern browsers.

Using a mixin like this saves you a lot of time by not having to rewrite those pesky vendor prefixes. Mixins can be used for virtually any repeatable code. Buttons, form fields, font stacks, and more are great use cases for mixins. I invite you to start building your own and experiment with the possibilities. I promise once you start using them you will see why they are a lifesaver in the Sass world.

Extends

Extending styles is a unique feature to Sass. Sometimes you may have an element with a base styling that you only want to change a few characteristics on such as error states in your application. The best way to illustrate this is by example. I’ll create another partial called _alerts.scss and add the following code. Again this partial is imported within our _styles.scss file so it gets compiled.

/*  _alerts.scss */

.alert {
    border: 1px solid #ddd;
    padding: 1em;
    color: #333;
}

.success {
    @extend .alert;
    border-color: green;
}

.warning {
    @extend .alert;
    border-color: yellow;
}

.danger {
    @extend .alert;
    border-color: red;
}

As you can see, rather than repeating ourselves we can use the @extend declaration to reuse the styles found within the .alert class. Each state of the alert then gets its own unique border-color.

The compiled CSS would then resemble something like this:

/* styles.css */

.alert, .success, .warning, .danger {
    border: 1px solid #dddddd;
    padding: 1em;
    color: #333333;
}

.success {
    border-color: green;
}

.warning {
    border-color: yellow;
}

.danger {
    border-color: red;
}

Be careful with @extends. While they are powerful they can become challenging to maintain when you application scales. I suggest using them on the lower level scale like error states just to keep things neat and tidy.

Operators

Have you ever wanted to do some math in your CSS? Well, with Sass it is now possible. More and more Sass-based components are being built using operations to declare things such as grids, consistent font-sizes, line-heights and more to make your website scale with ease.

Basic operators are available to use with Sass like +,-,*, \ and %.

For example, calculating somewhat dynamic font-sizes can occur like this:

/*_typography.scss - added to our scss folder and imported inside our styles.scss file */

$base-size: 1em; /* ~ 16px */

h1 {
  font-size: $base-size + 5em;    /* 6em */
}
h2 {
  font-size: $base-size + 3em;    /* 4em */
}
h3 {
  font-size: $base-size + 2em;    /* 3em */
}
h4 {
  font-size: $base-size;          /* 1em */
}
h5 {
  font-size: $base-size - .2em;   /* .8em */
}
h6 {
  font-size: $base-size - .5em;   /* .5em */
}

All of our headings have a $base-size variable applied to each. From there we make use of operations to figure new sizes for each. It can get more complex than this but I’m simply trying to illustrate how it works.

Conditionals

If we can use operators it makes sense to be able to use conditionals in our Sass right? Just like in a language like JavaScript or PHP we can make use of conditionals to test if conditions are true or false. Upon validation, our Sass is smart enough to output value depending on the condition being tested.

Here’s a quick example where I test if a div with the class of .box has padding less than or equal to 20px:

$padding: 40px;

.box {
    @if($padding <= 20px) {
        padding: $padding;
    } @else {
        padding: $padding / 2; /* 20px */
   }
}

This would simply compile to:

.box {
    padding: 20px;
}

Interpolation

Interpolation is a specific syntax within Sass that allows you to assign variables to selectors within your Sass code.

p {
    $font-size: 16px;
    $line-height: 24px;
    font: #{$font-size} / #{line-height};
}

Here I’ve defined a couple of variables which are passed through interpolation values which compiles to:

p {
  font: 16px/24px;
}

One of my favorite uses of interpolation is targeting all the heading selectors like so. Keep in mind that this requires Compass to work:

#{headings()} { 
    font-family: $raleway;
}

Outputs to:

h1, h2, h3, h4, h5, h6 {
  font-family: "Raleway", sans-serif;
}

Loops

Loops are very powerful for duplicating unique code in specific use cases within your application. A common approach I have used often deals with looping through background images and applying a new image for different blocks. Check out the following example which uses interpolation as I discussed in the last section:

/* Loops through each animal and outputs a unique background image based on naming conventions. */
@each $animal in bear, cow, chimp, zebra {
    .#{animal}-block {
        background-image: url('/images/#{$animal}.png');
    }
}

This code gets compiled to:

.bear-block {
  background-image: url('/images/bear.png'); }
.cow-block {
  background-image: url('/images/cow.png'); }
.chimp-block {
  background-image: url('/images/chimp.png'); }
.zebra-block {
  background-image: url('/images/zebra.png'); }

It’s important to note that your images must be named according to how you declare your variables within the interpolation fields.

Multiple assignments

The @each looping directive isn’t limited to just one variable. You can go one step further and add more than one assignment. For example:

@each $animal, $color in (bear, brown), (cow, black), (chimp, orange), (zebra, white) {
    .#{animal}-block {
        background-image: url('/images/#{$animal}.png');
        border: 1px solid $color;
    }
}

is compiled to:

.bear-block {
  background-image: url('/images/bear.png'); 
  border: 1px solid brown;
}
.cow-block {
  background-image: url('/images/cow.png'); 
  border: 1px solid black;
}
.chimp-block {
  background-image: url('/images/chimp.png'); 
  border: 1px solid orange;
}
.zebra-block {
  background-image: url('/images/zebra.png');
  border: 1px solid white;
}

A more practical approach could be heading sizes again which would resemble something like this:

@each $heading, $size in (h1: 3em, h2: 2em, h3: 1.5em, h4: 1em) {
    #{$heading} {
        font-size: $size;
    }
}

which gets compiled to:

h1 { 
    font-size: 3em; }
h2 { 
    font-size: 2em; }
h3 { 
    font-size: 1.5em; }
h4 { 
    font-size: 1em; }

Notice that we used a new declaration with the parentheses above. This makes use of Sass maps which are useful in associating keys with values much like an array in JavaScript or any other programming language.

Final Thoughts

I’ve only scratched the surface of what Sass has to offer. The whole point of the language is to offer a more DRY approach to authoring CSS which by nature is a very repetitive language. You can use Sass as a tool to help you write clearer and more consistent CSS that is easier to scale and update as time goes on. Learning Sass is very easy compared to other languages out there. If you are new to it then I suggest just starting with the basics. Once you see the potential it has you will discover how great it is and ultimately improve your development workflow.

Feature image illustration via http://sass-lang.com/

Link this article
Est. reading time: 17 minutes
Stats: 588 views

Categories