Why You Should Use Sass

02 Jan 2013

Sass is short for Syntactically Awesome Stylesheets, and is an extension of CSS3. Despite the long list of reasons why using Sass is a smart choice for CSS development, there are still many that hesitate to make the jump. This is something I understand well, as I withheld from using Sass for a long time.

"But I love hand-crafting my CSS, I don't want it processed first!"

This is something that I've heard as a reason for avoiding Sass or other preprocessors. As a matter of fact it is the excuse that I used for a long time before making the switch. Hell, I'm still guilty of going back to my past CSS syntax when I want something specific done that I've done many times before. However, this is certainly something I'm trying to get away from. The fact is, Sass makes things easier and the drawbacks are difficult to find. If you are unsure about small differences while writing your Sass, it even accepts plain CSS and compiles it with the rest of your Sass code no problem.

Let's dig into some of the best parts of Sass.

Nesting

Nesting selectors is one of the things that CSS developers have been clamoring for for years. Saving yourself typing time and keeping your code organized is the cornerstone of Sass, and nesting is a huge implementation of that.

For example, writing out your font styles is always a chore. Rewriting the word "font" before each selector and ending up with a block of unorganized styles is a help to no one. Now with Sass, you can simple nest them into a neat and organized list.

CSS

nav {
  font-family: serif;
  font-weight: bold;
  font-size: 1.2em;
}

Sass

nav {
 font: {
    family: serif;
    weight: bold;
    size: 1.2em;
  }
}

Mixins

Mixins are one of my absolute favorite parts of Sass. I many times find myself rewriting not just single selectors or rules, but entire chunks of code. Mixins are basically variables that contain these chunks of code and allow you to reuse it as many times as you'd like throughout your stylesheet.

The mixin syntax is @mixin code-chunk {**STYLE**} and can be included in your styles by adding @include code-chunk;

CSS

.bigbutton {
 border-radius:15px;
 border-color:#000000;
 border-style:solid;
 border-width:5px;
}

.smallbutton {
 border-radius:15px;
 border-color:#000000;
 border-style:solid;
 border-width:1px;
}

Sass

@mixin rounded-corners {
 border {
  radius:15px;
  color: #000000;
  style: solid;
 }
}

.bigbutton {@include rounded-corners; border-width:5px;};
.smallbutton {@include rounded-corners; border-width:1px;};

Not only is that simpler and much easier to look at, but that rounded-corners mixin can be used on any element that you want to have a similar style. Everyone benefits from recycling!

Extend

Extend is arguably the most useful feature of Sass. By using @extend in your style, you can make selectors inherit styles from other selectors. A good example of this can be found in Chris Eppstein's blog post announcing Sass 3.2.

Sass

%clearfix {
  overflow: none;
  *zoom: 1;
}

aside, footer {
  @extend %clearfix;
}

#grid-container {
  @extend %clearfix;
}

This produces the following:

aside, footer, #grid-container {
  overflow: none;
  *zoom: 1;
}

This can be used with the same philosophy as mixins (just used differently). If you want to make your stylesheets simple to write and easy to navigate later, reuse.

Also, there is a difference between mixins and extend, besides the fact that mixins can have arguments. When you use extend to create your new inheritance, doesn't just inherit the styles from that selector. Instead, it maintains the inherited styles from that selector and applies them to the selector that the extend is being placed on.

Once again, I'll let an excerpt from Chris' blog post show how this works.

Sass

#sidebar %link {
  text-decoration: underline;
}
p %link {
  color: blue;
}

a         { @extend %link; }
span.link { @extend %link; }
button    { @extend %link; }

Extending these selectors will then create this CSS:

#sidebar a, #sidebar span.link, #sidebar button {
  text-decoration: underline;
}

p a, p span.link, p button {
  color: blue;
}

Variables

Another developer favorite, variables are like miniature mixins. If you're fluent in other programming languages, you already know how much your workflow can be improved by intelligently using variables. One of the greatest benefits of Sass variables though, is that it allows math to be done on the variables. This is a huge time saver in CSS and is one of the reasons I regret not switching over a long time ago.

Variables are declared using the "$" character. All you need to do is declare it once at the beginning of your stylesheet, and you're free to use it as many times as you'd like throughout the rest of your code. An easy example of this is with colors.

$red:#F51B1B;

color:$red;

There it is, you'll never have to remember another hex value again! This is unbelievably convenient, especially with complicated color palettes or other extremely specific style guides that have minute details that you don't want to remember.

Being able to complete math operations with your CSS styles is another great implementation of Sass. Let's say I want to make sure that my padding on a div is always exactly 1/2 of the margin. Since I already have a variable set up for my margins, I can use that variable to set my padding as well.

$margin:5em;

.bigbox {
 padding: $margin / 2;
}

Alternatives and Other Preprocessors

There are a few alternatives to Sass if you'd like to go another direction. Even though I've settled on Sass as my go-to method for creating stylesheets, each person has their own preferences and it may not work the best of everyone.

LESS

LESS is similar to Sass in that it is a CSS preprocessor and it will let you do many of the things that Sass does. It is the default style code for Twitter Bootstrap is gaining users quickly.

Unfortunately I haven't worked with LESS enough to gather enough information for fair review, but a simple google search can take you to plenty of resources and reviews of LESS.

Haml

Created by Sass creator Hampton Catlin, Haml is an HTML preprocessor that has many of the same aims that Sass has for CSS. Though it hasn't caught on as quickly as Sass, there are plenty of devoted users of Haml and as it matures it will certainly gain more ground.

Here is a code sample from the Haml homepage.

.erb Template

<section class=”container”>
  <h1><%= post.title %></h1>
  <h2><%= post.subtitle %></h2>
  <div class=”content”>
    <%= post.content %>
  </div>
</section>

Haml

%section.container
  %h1= post.title
  %h2= post.subtitle
  .content = post.content<br />

As you can see, the code is much more simple and succinct. In large Ruby web apps this can be a huge time saver and can make your code look much neater and easier to go through. When you have lots of files each with many lines of code, this is an invaluable asset.

CoffeeScript

CoffeeScript is a preprocessor for Javascript. Similar to Sass, you write your code in much shorter and compact code, and it processes and spits out that code in plain Javascript. There has been plenty of debate sparked over CoffeeScript, but Javascript developers seem to be warming up to it as it matures and improves.

One of the points that CoffeeScript developers insist on is that it is just Javascript. With Sass, the main aim of the preprocessor is giving you extra functionality to work with. In CoffeeScript, rather, the aim is to create simpler and more beautiful looking code by removing some of the uglier parts of Javascript like the heavy use of semi-colons and braces.

Here's a code comparison of CoffeeScript and normal Javascript that is provided on the CoffeeScript homepage.

Javascript

var cubes, list, math, num, number, opposite, race, square,
  __slice = [].slice;

number = 42;

opposite = true;

if (opposite) {
  number = -42;
}

square = function(x) {
  return x * x;
};

list = [1, 2, 3, 4, 5];

math = {
  root: Math.sqrt,
  square: square,
  cube: function(x) {
    return x * square(x);
  }
};

race = function() {
  var runners, winner;
  winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  return print(winner, runners);
};

if (typeof elvis !== "undefined" && elvis !== null) {
  alert("I knew it!");
}

cubes = (function() {
  var _i, _len, _results;
  _results = [];
  for (_i = 0, _len = list.length; _i < _len; _i++) {
    num = list[_i];
    _results.push(math.cube(num));
  }
  return _results;
})();

CoffeeScript

# Assignment:
number   = 42
opposite = true

# Conditions:
number = -42 if opposite

# Functions:
square = (x) -> x * x

# Arrays:
list = [1, 2, 3, 4, 5]

# Objects:
math =
  root:   Math.sqrt
  square: square
  cube:   (x) -> x * square x

# Splats:
race = (winner, runners...) ->
  print winner, runners

# Existence:
alert "I knew it!" if elvis?

# Array comprehensions:
cubes = (math.cube num for num in list)

Looking at that comparison, it is fairly obvious why developers writing a lot of Javascript code would be intrigued by CoffeeScript.

Conclusion

I hope this post inspired you to at least try out some preprocessors and see how it fits into your workflow. After the initial pain of converting everything over, the amount of time you'll save along with all of the new implementations you can use will make you wonder why you ever hesitated to switch in the first place.