Introduction to SASS

Posted on Saturday July 13, 2013 / by Justin Navarro

What is SASS?

SASS (Syntactically Awesome Stylesheets) is an extension of CSS that adds power and elegance to the basic language. It allows you to use variables, nested rules, [[mixins, inline imports, and more, all with a fully CSS-compatible syntax. Sass helps keep large stylesheets well-organized, and get small stylesheets up and running quickly, particularly with the help of the Compass style library.

In short, SASS is a CSS preprocessor, like LESS and Stylus, that combines CSS and Ruby and it compiles your files to CSS on each save.

Here are some helpful links

What is Compass?

Compass is a framework that works along side of SASS to help speed up the coding process. For instance, Compass can help in CSS3 browser prefixes and basic styling techniques so you don't have to create or download any additional plugins or external files.

In order to use you will need to install Ruby, SASS, and Compass on your computer.

Installing Ruby

For Windows:

Go to Ruby site and download the latest version of Ruby.

For Ubuntu
sudo apt-get install ruby-full build-essential
sudo apt-get install rubygems
sudo gem install compass
sudo gem install sass

Before you can code in SASS you will have to tell SASS to watch your files so it can be compiled to CSS. Browsers do not read SASS files so it is necessary to tell SASS to watch and compile your files. There are two ways to tell SASS to watch your files:

Using the Command Prompt

Open Ruby Command Prompt by:

Create a Site Folder

Optional - If you don't have a site folder to store all your site files, you can use Compass to create one for you in the command prompt by typing

compass create '/path/to/file'

For instance, if I wanted to create a site folder called sass-rocks on my desktop then I would type:

compass create C:\Users\MyUser\Desktop\sass-rocks

Compass will generate the site folder and inside you will see the following:

.sass-cache
sass folder with some sass files
stylesheets folder with some css files
config.rg

Get SASS to watch your files

The first thing you should do is change your directory in the command prompt to your site folder.

cd '/path/to/file'

For instance, if I wanted to change the directory to a my site folder, sass-rocks, on the desktop

cd C:\Users\MyUser\Desktop\sass-rocks

Next is to write the command for SASS to watch your files. In my site folder, sass-rocks, I have a sass folder for all my sass files and a css folder for my css files. So I will write

sass --watch sass/:css/ --style compressed

The code above tells sass to watch my sass folder and compile to the css folder whenever I save something in the sass folder. NOTE - You could specify what you want to watch down to the file name but you would want to watch the whole folder just in case you create new sass files that you would want compiled.

You may have noticed, in the code above, the --style compressed command. That command tells SASS how to compile my CSS. There are four ways SASS can compile CSS into:

Nested
#main {
 color: #fff;
 background-color: #000; }
 #main p {
   width: 10em; }
.huge {
 font-size: 10em;
 font-weight: bold;
 text-decoration: underline; }
Expanded
#main {
 color: #fff;
 background-color: #000;
}
#main p {
 width: 10em;
}
.huge {
 font-size: 10em;
 font-weight: bold;
 text-decoration: underline;
}
Compressed
#main{color:#fff;background-color:#000}#main p{width:10em}.huge{font-size:10em;font-weight:bold;text-decoration:underline}
Compact
#main { color: #fff; background-color: #000; }
#main p { width: 10em; }
.huge { font-size: 10em; font-weight: bold; text-decoration: underline; }

When you are finished working and want to stop SASS from watching your files, go to your command prompt and press 'Ctrl + C'.

Using a GUI

There are a few GUI programs out there you can use to compile your SASS files so you don't have to type the commands in the command prompt. One of them is called Koala. You can visit http://koala-app.com/ and download the program. All the information you need are in the Koala App websites.

Creating your first SASS file

You can create a SASS file like any other file you create in your code editor. When you save the file, save it with the extension '.sass' or '.scss'. It is recommended that you use '.scss' extension. The difference between the two are listed below.

There are a few editors that doesn't recognize the SASS syntax. For instance, if you are using Sublime Text, you would notice when you type in your new SASS file that there are no syntax coloring. Fortunately, you can download that syntax in Sublime Text:

SASS vs SCSS Extension

SASS was created roughly 5 years ago. When it first came out, it used the '.sass' extension and you coded it more like Ruby. Which means:

The '.scss' extension is the third verison of SASS. Unlike the other verisons of SASS, you can write SASS (with the '.scss') exactly how you will write a CSS file. The '.scss' (Sassy CSS) extension was created to make it easier to learn SASS.

While writing a '.sass' extension makes your code easier to read and more concised, the '.scss' is more expressive, modular, and easier to learn for CSS devs.

Comments

There are two ways to write comments in SASS.

The multi-line comment

/* comments */

The double slash single-line comment

// comment

However, SASS treats comments a little differently than what you might expect. First off, the multi-line comment is valid in CSS comment. So if you make any multi-line comments in SASS then they will appear in the CSS file. But single-line comment is not a valid CSS comment. So SASS will not compile single-line comments to CSS, meaning you will only see them in SASS. So if you want to make comments in SASS and don't want others to see them in the CSS file, then use single-line comments.

Errors

From time to time, we all make mistakes in our code. It is normal. But what happens when you make a mistake in SASS? How will that look like in the CSS or browser?

You will see something like this in the browser

Syntax error: Invalid CSS after "...d-column-color" : expected ":", was "rgba(0,0,...)"
on line 9 of...

And your CSS file will be filled with a bunch of grey text that says 'error' along with whats written above. Don't fret. Just read the error to find out whats wrong and fix it. Once its fixed, everything will be normal again.

Managing Multiple SASS Files

Like CSS, you can have multiple SASS files for one site. However, SASS takes it one step further by giving you the option to compile several SASS files into one CSS file.

Let's say I have four SASS files:

I want fonts.scss, mobile.scss, and tablet.scss to merge into main.scss during the compiling process to become main.css. Meaning all the code from fonts.scss, mobile.scss, and tablet.scss will be in the main.css including the code from main.scss.

In the main.scss file, you need to add the '@import'. For this instance, I will write

@import 'fonts', 'mobile', tablet;

Notice that the SASS version of '@import' is slightly different from the CSS version. In the SASS version, you don't have to add the 'url()', you can import multiple files on one line, and you don't have to write the extension of the SASS files you are importing.

Right now, if I compile my main.scss file, it will compile four CSS files. To get SASS to compile one CSS file, I would have to rename the three SASS files, I am importing, to have an underscore in front of the file name. So my SASS files will become:

Now if I compile my SASS files, I will get one CSS file.

Using Compass

As mentioned before, Compass is a framework that works together with SASS. A lot of things you use normally, like prefixes, can be called from Compass so you don't have to write the whole thing yourself. For instance, lets say you want to write some CSS but you have to write all the prefixes so they can be viewed in each browser. That means you have to write the same CSS up to FIVE TIMES! And what if you have to make edits? You will have to edit those five CSS properties everytime. Wouldn't it be better to only write it once? Compass can help with that.

'So how do I use it?'

Since we are on the topic of prefixes, let's start there. In your main SASS file, you will have to '@import' Compass. Its best that you place the '@import' for Compass on the very first line since browsers read code from top to bottom.

@import 'compass/css3';

Next, you will have to write some SASS. Let's say I want to create a header with a border radius of 15px.

header {
   @include border-radius(15px);
}

Your CSS will look like:

header {
 -webkit-border-radius: 15px;
 -moz-border-radius: 15px;
 -ms-border-radius: 15px;
 -o-border-radius: 15px;
 border-radius: 15px;
}

Compass also has a CSS reset like normalise and some basic styling that you may find useful. To find out more, check out their reference guide here

Nesting in SASS

SASS likes to avoid repetition. One way to avoid repetition and having to rewrite a lot of code is to nest selectors, IDs, and classes within each other. Notice the usage of '&' with ':first-child' - means there are no spaces between the parent and that child becoming a parent selector.

In SASS
ul {
   margin: 10px;
   min-height: 10px;
   padding: 0;
   width: 100%;
   img {
     width: 30px;
   }
   &:first-child {
     display: none;
   }
 }
In CSS
ul {
    margin: 10px;
    min-height: 10px;
    padding: 0;
    width: 100%;
}
ul img {
    width: 30px;
}
ul:first-child {
    display: none;
}

You can also nest CSS properties

In SASS
#text {
    color: black;
    font: {
        family: arial;
        size: 14px;
        weight: normal;
     }
     border: {
        color: red;
        size: 1px;
        style: solid;
     }
     text-align: center;
}
In CSS
#text {
    color: black;
    font-family: arial;
    font-size: 14px;
    font-weight: normal;
    border-color: red;
    border-size: 1px;
    border-style: solid;
    text-align: center;
}
@extend SASS

'@extend' extends one ID, class, or selector CSS styles with another. In CSS, multiple IDs, classes, and selectors sharing one CSS are separated by commas. You will recognize it in CSS as

header, nav {
   /* CSS Styles */
}

To write that in SASS, you could follow the same method as CSS and separate with a comma.

header, nav {
  // SASS Styles
}

Or, you can use the @extend method

header {
   // SASS Styles
}

nav {
   @extend header;
}

The reason the '@extend' exists is because you can still add SASS styles specific to nav while extending the header styles.

header {
   // SASS Styles
}

nav {
   @extend header;
   // Nav only SASS Styles
}

Variables in SASS

If you are using the same color or value in multiples places, or need to do some math then use variables. SASS supports variables and basic math operations.

To write a variable, you will need a '$' and the variable name. The variable name can be anything you want as long as it starts with a letter or underscore.

Lets say I want to create a variable called height and have it equal to 200px.

$height: 200px;

article {
   height: $height;
}
In CSS
article {
   height: 200px;
}

Global vs Local Variables

Local variables can only be used within your property, ID, class, or mixin and are placed inside the curly brackets where you want to use the variable in.

header {
   $full: 100%;
   color: #000;
   height: 150px;
   width: $full;
   img {
     width: $full;
   }
}

Global variables can be used anywhere in your code and are placed at the beginning of your code or on a separate SASS file.

$full: 100%;

header {
   color: #000;
   height: 150px;
   width: $full;
   img {
     width: $full;
   }
}
article {
   height: $full;
   left: 0;
   position: absolute;
   top: 0;
   width: $full;
}

If you have a global and local variable with the same variable name, the local variable will be treated as a global variable and the last variable read by SASS will be used.

$full: red;

article {
   $full: 100%;
   height: $full;
}
header {
   color: $full;
}
In CSS
article {
   height: 100%;
}
header {
   color: 100%;
}

Interpolation #{}

There are certain situations, when writing a variable, that can confuse SASS during compiling and it will create an error. Like placing variable in a string, no spaces between the variable and the next word, or writing a variable next to a class, ID or property. Under the conditions you will want to write your variable as

 #{$var-name}

Lets say I want to create a variable with a relative path of my site folder for all the images I am going to call in my SASS file.

$path: '../images/';

body {
   background: url('#{$path}bgImg.jpg');
}
In CSS
body {
   background: url('../images/bgImg.jpg');
}

Variables and Math

You can use basic math (add, subtract, multiply, and division) with variables. Lets say I have two containers that are floating left inside a parent container with a width of 1000px. I want the left container to be wider so it'll contain the main content and the right container to be more like a sidebar. Instead of doing the math myself to make both child containers fit the width of 1000px from its parent container, I could have SASS do the math for me.

One way to do so is

$mainWidth: 1000px;
$contentArea: 726px;
#parentContainer {
   width: $mainWidth;
   #leftContainer {
       width: $contentArea;
   }
   #rightContainer {
       width: $mainWidth - $contentArea;
   }
}

In CSS, This works because no matter how many times I change the value of $contentArea, SASS will create the difference for me for #rightContainer.

#parentContainer {
   width: 1000px;
}
#parentContainer #leftContainer {
   width: 726px;
}
#parentContainer #rightContainer {
   width: 264px;
}

Mixins in SASS

Mixins are similar to variables but mixins can contain full CSS rules.

Lets say I wanted to create a button that I will use multiple times throughout my site for links and submit buttons. Instead of coding the button multiple times in the CSS, I will create a mixin and call it throughout my SASS so the actual code for the button is only written once.

Somewhere in my SASS file or in a separate SASS file, I will begin by writing the mixin. To start off you have to write '@mixin' and the mixin name followed by the curly braces. I'll be naming my mixin, button.

@mixin button { }

Then add all the code between the curly braces just like how you will normally write CSS and SASS.

@mixin button {
 border: 1px solid #000;
 display: block;
 font-size: 1em;
 padding: .75em 0;
 text-align: center;
 text-decoration: none;
 width: 240px;
}

Finally, call the mixin by using @include. I will include the button to my a for the links on my site. Notice you will have call the mixin name with the @include.

a {
   @include button;
}
In CSS
a {
 border: 1px solid #000;
 display: block;
 font-size: 1em;
 padding: .75em 0;
 text-align: center;
 text-decoration: none;
 width: 240px;
}

Arguments

Arguments are basically variables in mixins and are defined when you include the mixin. Multiple variables and arguments are separated by a comma.

@mixin pretty-border($color, $width) {
   border: {
     color: $color;
     width: $width;
     style: dashed;
   }
}

p {
   @include pretty-border(#900, 3px);
}
In CSS
p {
 border-color: #900;
 border-width: 3px;
 border-style: dashed;
}

Mixins can also specify default values for their arguments. If you have a default value for a variable then you don't need to pass that argument in the '@include'.

@mixin pretty-border($color, $width: 3px) {
   border: {
     color: $color;
     width: $width;
     style: dashed;
   }
}

p {
   @include pretty-border(#900);
}
In CSS
p {
 border-color: #900;
 border-width: 3px;
 border-style: dashed;
}

When writing the variables in the mixin, the variables without a default value has to come before the variables with a default value otherwise you will get an error.

This is wrong
@mixin button($size: 100px, $value) { }
This is right
@mixin button($value, $size: 100px) { }

Also, when defining your arguments in the '@include', it has to be in the same order as how you written it in the '@mixin'.

@mixin button($value, $size: 100px) { }

@include button(arial, 100px);

If you do not want to write the arguments in the '@include' the same order as in the '@mixin' then you will get an error unless you specify by writing the variables in the '@include'.

@mixin button($value, $size: 100px) { }

@include button($size: 100px, $value: arial);

Loops in SASS

@For

'@for' repeatedly outputs a set of styles. For each repetition, a counter variable is used to adjust the output. There are two ways to write a for loop in SASS

@for $i from 1 through 2 {
    // Styling
}

or

@for $i from 1 to 2 {
    // Styling
}

The only difference between the two are the words 'through' and 'to'.

The word 'through' means the loop range includes the start and end values, in this case, 1 and 2. Meaning if you ran the code above with the word 'through' then you will get two instances from that loop.

The word 'to' means the loop range runs up to but not including the end value, in this case, 2. Meaning if you ran the code above with the word 'to' then you will get one instance from that loop.

To write the styling that goes between the curly braces, you must remember to place the counter variable. Let say I want a loop of two instances with a width that increases on each instance.

@for $i from 1 through 2 {
   .item-#{$i} { width: 10px * $i }
}

or

@for $i from 1 to 3 {
   .item-#{$i} { width: 10px * $i }
}
In CSS
.item-1 {
  width: 10px;
}

.item-2 {
  width: 20px;
}
@each

'@each' is similar to writing an array where you have a variable that has multiple definitions in a list. There will be a loop for each definition listed and each definition would output into the instance. Meaning, if you have a list of five words in a variable then your loop will run five times and each instance will contain one of those five words.

For instance, I am creating a social icon section in the footer. I will need an icon for Facebook, Twitter, Google+, and Youtube. I want the user to be able to click on it each icon and follow my social shenanigans.

There are two ways to write an @each. My variable will be $social for the list of icons. The first step is to write the @each, variable, and the list.

@each $social in facebook, twitter, google, youtube {

}

Inside the curly braces, I will write my CSS styles that will be looped for each social icon. Notice I have a variable, $social, in the class name and in the image name.

@each $social in facebook, twitter, google, youtube {
  .#{$social} {
     background: url('../images/#{$social}.png');
  }
}
In CSS
.facebook {
 background: url("../images/facebook.png");
}

.twitter {
  background: url("../images/twitter.png");
}

.google {
  background: url("../images/google.png");
}

.youtube {
  background: url("../images/youtube.png");
}

Another way to write the '@each' is to put the list of my social media into another variable called $icons, and call $icons in the line with $social. Either way gives the same results.

$icons: (facebook, twitter, google, youtube);
@each $social in $icons {
  .#{$social} {
     background: url('../images/#{$social}.png');
  }
}
@while

'@while' is similar to '@for' where it will repeatedly outputs the styles until the statement equals false.

First, I have to create a counter variable.

$i: 6;

Next I will have to create an '@while' statement. My '@while' statement says to create a loop as long as my counter variable is greater than 0.

$i: 6;

@while $i > 0 { }

Finally you will have to write the output styles. Notice the '$i: $i - 2;'. That and '$i > 0' tells SASS how many loops to create.

$i: 6;

@while $i > 0 {
   .item-#{$i} { width: 2em * $i }
   $i: $i - 2;
}
In CSS
.item-6 {
  width: 12em;
}

.item-4 {
  width: 8em;
}

.item-2 {
  width: 4em;
}

If/else in SASS

@if

'@if' is a condition that uses styles nested beneath it if the condiiton returns anything other than false or null.

p {
   @if 1 + 1 == 2 { border: 1px solid;  }
   @if 5 < 3      { border: 2px dotted; }
   @if null       { border: 3px double; }
}
In CSS
p {
 border: 1px solid;
}

You can also use '@if' in mixins. Lets say I have a background color on the body and I want the text color to change based on the background color options I give. I will give my background color a default value of white.

@mixin color($bg: white) {
   background: $bg;
   @if $bg == white {
     color: #000;
   }
   @if $bg == black {
     color: #fff;
   }
   @if $bg == #ddd {
     color: #888;
   }
}

Now when I call the mixin with '@include' and I don't call an argument then my default background color will white and my text is black.

body {
   @include color;
}

If I decide to call an argument with my '@include' then I could use one of the other two color options I gave. So I call the argument with a black background color

body {
   @include color(black);
}

I will get this in CSS

s
body {
   background: black;
   color: #fff;
}
@else if

If you have more than one conditions in your statement then '@else if' can be followed by the initial '@if'.

Lets say I have a parent container that has two children containers that are floating left with a width of 50% if the width of the parent container is greater than or equal to 1000px. If the parent container is less than 1000px, then the two children containers float will be set to none and width will be set to 100%.

$width: 1000px;

.parent {
   width: $width;
   @if $width >= 1000px {
     .children {
       float: left;
       width: 50%;
     }
   }
   @else if @width < 1000px {
     .child {
       float: none;
       width: 100%;
     }
   }
}
In CSS
.parent {
  width: 1000px;
}

.parent .children {
  float: left;
  width: 50%;
}
@else

The @else is used when all the @if are not meant. There can be multiple @if but only one @else.

I want to create a triangle. For my triangle, I want to be able to control the size, color, and the direction of the tip. In order to do so, I would need to create a mixin. My width and height needs to be set at zero since I control the size of the triangle through the border.

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

If I was to call this mixin's direction with 'up' then it would place the given style. If I don't, then SASS would move down my condition to match the direction with what I called in the '@include'. If it cant match the two then it would place the styles in '@else'.

#triangleContainer {
   @include triangle(60px, blue);
}
In CSS
#triangleContainer {
   height: 0;
   width: 0;
   border-bottom: 60px solid transparent;
   border-top: 60px solid transparent;
   border-right: 60px solid blue;
}

Functions in SASS

Functions are similar to mixins as you can create reusable code but functions only return a single value.

Built-in Functions

SASS has a bunch of functions built-in already. To see the list of built-in functions, go here.

The list of built-in functions can be a little confusing but don't worry. The built-in functions list are divided into categories like rgb, hsl, opacity, etc. Each function shows the function name and the function's variable in parenthesis with a brief description below.

function-name($function-variable)
description

Read down the list and see if there are anything you may want to use. You might recognize a few functions like rgba() and rgb() if you ever used them in CSS.

To use these functions, all you have to do is call them in your SASS file. For instance, I will use rgba() and put in the red, green, blue, and alpha values.

p {
   color: rgba(0,0,0,0.5);
}

But what if you don't know the red, green, and blue values? SASS can convert your hexadecimal colors to rgb values. So you can write it like

p {
   color: rgba(#000,0.5)
}

Another built-in function you may be interested in are lighten() and darken(). You can use these functions to lighten or darken your colors without having to find a new hexadecimal. Both of these functions require a '$color' and a '$amount'.

#beer {
  background-color: darken(#eee, 20%);
  color: lighten(#000, 70%);
}
In CSS
#beer {
  background-color: #bbbbbb;
  color: #b3b3b3;
}
Creating Functions

As great as it is to have a bunch of functions already built into SASS, sometimes you have to create your own functions. When creating a function you will need the '@function' to define a function, @return to return data, and math.

Are you completely use to pixels? Are ems completely foreign to you? Guess what? You can build a function that can convert your pixels into ems.

To create this I am going to use

target / context = result

The ratio above is used by many front-end devs to calculate things like font sizes. To start, I'm going to need the '@function' and a function name. I'm going to name this function 'pxtoem'.

@function pxtoem() {

}

Next, I will add my variables. I am going to name my variables based off the ratio above.

@function pxtoem($target, $context) {

}

Finally, I will need the '@return' to return my result and some math.

@function pxtoem($target, $context) {
   @return ($target/$context)+0em;
}

The '$target' is the size you want yo'ur element to be. The '$context' is the based size which can be anything you want but it is usually 16px because thats the default browser font size. The function will divide '$target' and '$context' and add it to '0em' giving you the result.

To call this function, all you need to do is write the function name, your target size, and your context size. Don't write your values with the word 'px'.

p {
   font-size: pxtoem(18, 16);
}
In CSS
p {
   font-size: 1.125em;
}

What if your based size will always be 16 and/or you are tired of writing the based size with the target size? Simple. SASS functions accept arguments.

@function pxtoem($target, $context: 16) {
   @return ($target/$context)+0em;
}

In the code above, I gave '$context' a default value of 16. Now you don't have to write the based size everytime.

p {
   font-size: pxtoem(18);
}
In CSS
p {
   font-size: 1.125em;
}

If you think writing 'pxtoem($value)' is still too much, then you can change the function name and/or create a snippet in your code editor.