SCSS

CSS preprocessors like SASS, LESS and Stylus have gained increasing popularity over the last couple of years as they extend the capabilities of ordinary CSS with mechanisms that used to be available only in tradtional programming languages. On its own, cascading style sheets (CSS) is a relatively dumb markup language that does not scale very well and tends to be quiet repetitive. Intially released in 1996 by the World Wide Web Consortium in an attempt to separate the presentation of HTML or XHTML documents from the content, it provided more flexibility to style individual page elements and the sharing of those styles over multiple pages. However, the limitations of this approach became quickly obvious. With vanilla CSS you have to write the same styling for different selectors multiple times. Due to this accumulation, the code base becomes bloated, less maintainable and unorganized.

Now, the idea of a preprocessor is to take preprocessed input in a certain form and compile it into the desired format, while applying a set of syntactical rules. The advantage is that the preprocessor can add logic and functionality when interpreting into the final form that was previously not known. Nevertheless, a CSS preprocessor does not help you to write better CSS. Badly written scss, less or styl will compile into bad CSS. You could even write plain, old CSS and the preprocessor would not bother. In order to take advantage of the aforementioned benefits, it is the user´s responsibility to internalize the functionality of the chosen stylesheet language, logically organize the code base and apply the DRY principle (don´t repeat yourself).

The following article takes a closer, certainly opinionated look at the most popular stylesheet language SASS in its flavour SCSS.

Ruby & Compass vs Nodejs, LibSass & Grunt

The official implementation of SASS / SCSS is coded in Ruby, which requires you to install an application that brings in all necessary dependencies and compiles SCSS into CSS, such as Compass.app, CodeKit, Koala or Prepros. Out of these apps, Compass has traditonally been the most popular as it comes with a large library of reusable CSS3 patterns and helper functions. The alternative way is to use the command line and install Ruby (on Mac it comes pre-installed, on most Linux distribution you have to install it) and the Ruby Sass Gem manually:

sudo gem install sass

Despite its beautiful, expresssive syntax and the related productivity advantages, I personally don´t like to depend on Ruby in my front-end workflow. As an interpreted language, Ruby is slow compared to C-type languages. And that translates directly to an app like Compass: Compiling multiple SASS-files, especially in large projects, can be unbearably slow depending on your hardware.

Luckily, there is LibSass, “a C/C++ port of the Sass engine “, which can be used in combination with Node.js and Grunt or Gulp; JavaScript task runners that automate repetitive tasks in your front-end workflow. While there is a recent hype around Gulp as the flashy, new toy of the cool children, I still prefer to use Grunt. Although I have to admit that Gulp´s less verbose syntax is more attractive and requires less configuration, Grunt still offers a larger pool of stable plugins.

A fantastic Grunt plugin that allows you to compile SCSS into CSS using the LibSass library is grunt-sass, which you can add to your package.json with the following:

npm install --save-dev grunt-sass

Configuration in your gruntfile.js is pretty straight forward:

require('load-grunt-tasks')(grunt); // npm install --save-dev load-grunt-tasks

grunt.initConfig({
    sass: {
        options: {
            sourceMap: true
        },
        dist: {
            files: {
                'main.css': 'main.scss'
            }
        }
    }
});

grunt.registerTask('default', ['sass']);

Some critics have argued that CSS preprocessors make debugging more difficult. In the recent grunt-sass release, you can produce source maps, which allow you to track the individual, combined CSS-components back to the original SCSS-sources to facilitate debugging. A drawback, however, is the circumstance that grunt-sass only compiles the SCSS-flavour of SASS, which uses curly brackets and semicolons like CSS. I prefer SCSS syntax over SASS as it appears to me cleaner and more organized, but that is just personal preference.

Furthermore, the LibSass library is currently not at feature parity with the SASS 3.2 release. At the time of writing, the current SASS release is 3.4.5. Despite this circumstance, I am convinced that development will catch up when it gains more popularity as performance-wise it is the future of SASS compilation.

If you are coming from Compass and need a replacement for the library, I recommend to have a look at Bourbon, a “simple and lightweight mixin library for SASS”. You do not have to install it using the Ruby Gem, but can pull it in via Bower to match the Grunt workflow.

Syntax

A very detailed representation of the complete SASS / SCSS functionality can be found in the official documentation. The following explanations represent a basic overview of the key features that should get you going quickly. I used the SCSS syntax as my personal preference. If you want to play with the examples without having to setup a development environment, I recommend to use SassMeister, which compiles SASS into CSS in the browser.

Using Variables

SCSS allows you to define variables, which can be reused throughout your code. Variables are defined with the $ sign, followed by the variable name and the CSS property value. Variables are available within the same level of nested selectors where they have been defined but can be assigned globally using !global. You should name your variables as semantic and specific as possible to avoid confusion.

$brand-color: #ff3838;
$footer-height: 200px;
$footer-font: Helvetica, sans-serif;

#footer {
    color: $brand-color;
    font: $footer-font;
    height: $footer-height;
}

This compiles into the following CSS:

#footer {
  color: #ff3838;
  font: Helvetica, sans-serif;
  height: 200px;
}

Nesting your Code

Nesting is a key feature of SCSS that helps you to avoid writing repetitive code and reduces the complexity of your CSS. When using nestings, the inner rules only apply within the outer rule’s selector. Let’s say you want to style various elements within your header, you could write something like this:

#header {
    a {
        color: #FF0000;
    }

    a:hover {
        color: #FF00FF;
    }

    p {
        color: #428bca;
        font-family: Arial, Helvetica, sans-serif;
        font-size: 120%;
    }

    .navbar {
        background-color: #CCCCCC;
        border-top: 1px solid #000000;
        border-bottom: 1px solid #000000;
    }
}

This will compile into the following CSS:

#header a {
  color: #FF0000;
}
#header a:hover {
  color: #FF00FF;
}
#header p {
  color: #428bca;
  font-family: Arial, Helvetica, sans-serif;
  font-size: 120%;
}
#header .navbar {
  background-color: #CCCCCC;
  border-top: 1px solid #000000;
  border-bottom: 1px solid #000000;
}

Importing Files & Partials

Instead of putting all CSS in one file, SCSS allows you to split and organize your code in a modular way. You can either import complete files (e.g. normalize.scss) or partials (e.g. _settings.scss), which are named with an underscore before the file name. The difference is that the content of partial files is not directly compiled into CSS. The SCSS of the partial is imported as if it would be part of the base file. This allows you to organize your CSS in different functional areas (e.g. grid, colors, typography, reset) to facilitate maintenance. During the compilation process, all imported files will then be merged together in one central CSS file. For example, you could have a main.scss into which you import several files that you want to combine (_colors.scss, _typography.scss).

// _colors.scss

$darkgrey: #333333;
$lightblue: #667aff;
// _typography.scss

$heading-font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
$heading-font-weight: 400;

.h1, .h2, .h3, .h4, .h5, .h6 { font-family: $heading-font-family; font-weight: $heading-font-weight; }
.h1, .h2 { line-height: 1.1; }
.h3, .h4 { line-height: 1.3; }
.h1 { font-size: 400%; letter-spacing: -2px; color: $lightblue;}
.h2 { font-size: 250%; letter-spacing: -1px; color: $darkgrey;}
.h3 { font-size: 200%; }
.h4 { font-size: 180%; }
.h5 { font-size: 130%; }

Both partials can be imported into the base file using the @import function:

@import "colors";
@import "typography";

body {
  margin: 0;
}

This will compile into the following CSS:

.h1, .h2, .h3, .h4, .h5, .h6 {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
  font-weight: 400; }

.h1, .h2 {
  line-height: 1.1; }

.h3, .h4 {
  line-height: 1.3; }

.h1 {
  font-size: 400%;
  letter-spacing: -2px;
  color: #667aff; }

.h2 {
  font-size: 250%;
  letter-spacing: -1px;
  color: #333333; }

.h3 {
  font-size: 200%; }

.h4 {
  font-size: 180%; }

.h5 {
  font-size: 130%; }

body {
  margin: 0; }

Working with Mixins

Mixins are reusable CSS patterns that usually include vendor specific prefixes for improved cross-browser compatibility. Because CSS does not support mixins by default, the required CSS patterns have to be repeated in each location. SASS gives users the possibility to define a mixin once, using the @mixin function, followed by the name and optional arguments. The mixin can then be called at a specific location by using @include followed by the assigned name, without having to repeat the complete CSS block. In the following example, a mixin is used to define a reusable box shadow:

@mixin text-shadow {
    -webkit-box-shadow: 7px 10px 5px 0px rgba(0,0,0,0.75);
    -moz-box-shadow: 7px 10px 5px 0px rgba(0,0,0,0.75);
    box-shadow: 7px 10px 5px 0px rgba(0,0,0,0.75);
}

.box { @include text-shadow;}

This compiles into the following CSS:

.box {
  -webkit-box-shadow: 7px 10px 5px 0px rgba(0, 0, 0, 0.75);
  -moz-box-shadow: 7px 10px 5px 0px rgba(0, 0, 0, 0.75);
  box-shadow: 7px 10px 5px 0px rgba(0, 0, 0, 0.75);
}

Extend & Inheritance

Using the @extend feature, SCSS gives the possibility to share CSS properties between selectors. This applies in a situation, where one class should have the styles of another class while providing its own additonal CSS properties. This well-known concept from object-oriented programming is called inheritance: Some properties from the parent element are inherited by one or more child elements. In the following example, the .button-class is used to define the basic styling, which is inherited by more specific classes adding their own styling:

.button {
    font-family: Arial;
      color: #ffffff;
      font-size: 20px;
      background: #a3a3a3;
      padding: 10px 20px 10px 20px;
      text-decoration: none
}

.red-button {
    @extend .button;
    background: red;
}

.green-button {
    @extend .button;
    background: green;
}

This is compiled into the following CSS:

.button, .red-button, .green-button {
  font-family: Arial;
  color: #ffffff;
  font-size: 20px;
  background: #a3a3a3;
  padding: 10px 20px 10px 20px;
  text-decoration: none;
}

.red-button {
  background: red;
}

.green-button {
  background: green;
}

All styles defined in .button are also applied to the more specific clasess .red-button and .green-button.

Mathematical Operators

SASS can perform standard mathematical operations on numbers, including addition, subtraction, multiplication, division as well as modulo. Equality (== and =!) and relational operators (<, >, <=, >=) are also supported. Numbers need to have the same unit measure. The order of arithemtic operations can be modified using parenthesis.

$width: 960px;
$margin: 20px;

.box {
    width: $width/2;                   // Division
    margin: $margin * 2;               // Multiplication
    margin-bottom: $margin + 10px;     // Addition    
    font: 20px - 8px;                  // Subtraction
    color: #ff0000 + #008000;          // Arithmetic addition of hex values
    height: 250px + (25 * 2);          // Using parenthesis 
}

This is compiled into the following CSS:

.box {
  width: 480px;
  margin: 40px;
  margin-bottom: 30px;
  font: 12px;
  color: #ff8000;
  height: 300px;
}

String Operations

Besides the mathematical operations, SCSS allows you to concatenate strings and even interpolate variables:

$name: foo;
$font-size: 12px;
$attr: border;
$state: solid;

/* Interpolation */

p.#{$name} {                            
  font: #{$font-size};
  #{$attr}: 2px #{$state};
}

/* Concatenation */

$value: fun;

p::before { 
    content: "SCSS is #{fun}.";
}

This is compiled into the following CSS:

/* Interpolation */
p.foo {
  font: 12px;
  border: 2px solid;
}

/* Concatenation */
p::before {
  content: "SCSS is fun.";
}

Building Functions

A more advanced feature of SASS is the ability to define functions. A function is a type of routine or procedure that performs a specific task. Functions in SASS can accept multiple arguments and can contain several statements, where the output of the function has to be called as a single value using @return. Functions can access mixins and globally defined variables. In the following example, a simple function, called “em”, accepting two arguments $px and $base, is used to convert pixel size to em:

$body-font-size: 16px;

body {
    font-size: $body-font-size;
}

/* Define the function */

@function em($px, $base: $body-font-size) {
    @return ($px / $base) * 1em;
}

/* Call the function */

.heading {
    font-size: em(36px);
}

This translates into the following CSS:

body {
  font-size: 16px;
}

.heading {
  font-size: 2.25em;
}

Conclusion

SASS offers an array of powerful features that extend the functionality of normal cascading style sheets and gives it a dynamic perspective previously known only from traditional programming languages. Gladly, SASS has a gentle learning curve and can be flexibly accomodated to the users requirements and skills. For further reference and detailed reading, I recommend the offical SASS documentation, as well as the SassWay blog that features interesting posts and tutorials on relevant topics.

Try out SASS online here