Getting Started with Sass
This is the updated version of an article originally published on March 1, 2013. Changes include: updated information, fixed broken links, code syntax highlighting, added featured image.
As websites and pages have become more complex, CSS quickly buckles under the weight. It’s still a thousand times better than tables for layout but it could present some limitations for those working with it.
This is where CSS preprocessors come in. They add a new layer of awesome on top of a syntax we already know and love. There are many CSS preprocessors out there, but I’m going to focus on the one that captured my heart: Sass.
You’re going to learn about the difference between Sass indented syntax and .scss
syntax, the range of tools you can choose from to work with Sass, fundamental language features and syntax, and some great Sass extensions that will make styling webpages quicker and fun.
Sass: A Quick Definition
Sass is a a CSS preprocessor. This is a piece of software that adds a nifty new feature-set to CSS like variables, nesting and mixins. You write in a slightly modified CSS-like syntax which is then processed into plain-ol’-CSS. This processing can either happen on your development environment as you’re coding or as a part of your deployment process.
My prefered method — as I’m not a server nerd and get scared by deployment scripts — is to have my preprocessing done right in my development workflow. (More on this later.)
Why Sass
This is the big question, and there is no single answer. For me, Sass provides the right tools, syntax and extensions. Sass has a huge community behind it and is constantly growing and evolving. There are loads of excellent add-ons and extensions which make Sass even better. Sass also gives you two writing style options.
Sass Indented Syntax
This is like the crazy, wise uncle of CSS: quirky, kinda funny looking, but ultimately quite smart. This syntax looks nothing like CSS — its goal is brevity. Instead of brackets and semicolons, it uses the indentation of lines to specify blocks. Where you’d use a semicolon to separate statements, it uses new lines.
#main
color: blue
font-size: 0.3em
a
font:
weight: bold
family: serif
&:hover
background-color: #eee
.scss
.scss
is essentially a subset of the CSS3 syntax. This means that every valid CSS3 stylesheet is valid.scss
as well.
#main {
color: blue;
font-size: 0.3em;
a {
font: {
weight: bold;
family: serif;
}
&:hover {
background-color: #eee;
}
}
}
This is my preferred syntax and what I’ll be using to show examples throughout this article. So without further ado, let’s get cracking.
Sass Workflow and Tools
Sass Workflow
There is a slight shift in paradigm required to get into the Sass way. The main point being that you will never ever edit or commit your .css files. The only way to change the CSS is through the .scss
files. Once you save your .scss
file, the magic of the preprocessor will convert it to regular CSS. The moment you start editing your .css files is the moment the sky starts to fill with black holes…
There are two common ways to roll the preprocessor into your workflow. The first is to do it at build time. This will require some setup on your development and live environments using a parser for the programming language you choose. Rails 3.1 and up ships with Sass. If you use PHP, .NET or Java you’re in luck, as there are ports for those platforms. You could also roll it into a GRUNT/Gulp task or get Webpack to run the procressing on build.
If none of this makes sense to you, don’t be afraid! The second option is much more beginner-friendly: use a simple GUI on your development machine and compile as you go. You will need one of the following tools.
GUI (Graphical User Interface) Tools for a Sass Workflow
-
LiveReload
This magical tool does a whole array of cool things, one of which is compiling Sass. LiveReload monitors changes in the file system. As soon as you save a file, it is preprocessed as needed, and the browser is refreshed. This is a great speedy kick to your web dev workflow
-
CodeKit
This is a Mac-only app very similar to LiveReload and includes script minification, image compression and code hinting. This is the software I’ve opted for and love dearly
-
Prepros
This is a cross-platform (Linux, Mac, and Windows) GUI tool for compiling Sass and other preprocessor languages. It’s really feature rich and at the time of writing it’s available for free unlimited trial.
Let’s Start Coding Sass, Already!
Sass Nesting
This is probably the most fun but also the most dangerous part of Sass. Let’s consider the following two examples.
Example 1 — Good nesting
#navbar {
width: 80%;
height: 23px;
ul { list-style-type: none; }
li {
float: left;
a { font-weight: bold; }
}
}
Example 2 — Bad nesting
div#main {
#sidebar {
#navbar {
width: 80%;
height: 23px;
aside {
div {
ul {
list-style-type: none;
li {
float: left;
a {
font-weight: bold;
}
}
}
}
}
}
}
}
The reason Example 2 is bad is because the resulting CSS will have far too specific selectors:
div#main #sidebar #navbar {}
div#main #sidebar #navbar aside div ul {}
div#main #sidebar #navbar aside div ul li {}
div#main #sidebar #navbar aside div ul li a {}
Let’s all agree that’s a nightmare.
One of the guiding principles of modern CSS should be the principle of modular code, that is to say, bits of code that you can reuse without having to rely on the structure of your markup. For more information on this idea, look into OOCSS and SMACSS.
There’s a de facto rule called The Inception Rule that simply states you should never nest more than four selectors deep.
Sass Variables
$site_max_width: 960px;
$font_color: $333;
$link_color: $00c;
$font_family: Arial, sans-serif;
$font_size: 16px;
$line_height: percentage(20px / $font_size);
body {
color: $font_color;
font {
size: $font_size;
family: $font_family;
}
line-height: $line_height;
}
#main {
width: 100%;
max-width: $site_max_width;
}
We’re all familiar with variables and use them in our JavaScript, etc. This is the exact same idea, but with CSS. Now, when a client asks you to change that blue to a slightly more greeny-blue (with more pop), you can simply go to your variables and update that one instance. You can also use built-in Sass functions and operators as well as reference other variables in the declarations.
Sass Functions and Operators
Like any programming language, Sass comes with a suite of functions and standard operators. There are many functions that will help you deal with number, text and colors. And numbers (including those with units) have all the math operators you’ll ever need: +
, -
, *
, /
and %
.
Have a look at the documentation to see the list of goodness available.
Sass Mixins
Mixins are one of the most powerful parts of Sass and really allow you to get creative. A mixin is a collection of of re-usable styles, properties and selectors. You could think of a mixin as a macro or snippet for regular re-use.
A good example of a mixin is one that can handle those annoying vendor prefixes, like the one below:
@mixin box-shadow($shadow) {
-webkit-box-shadow: $shadow;
-moz-box-shadow: $shadow;
box-shadow: $shadow;
}
Or for hiding text (often used with image replacement techniques):
@mixin hide-text {
font: 0/0 a;
color: transparent;
text-shadow: none;
background-color: transparent;
border: 0;
}
Needless to say, you’ll be spending a lot of time coming up with your own personal arsenal of mixins to use on all your projects.
Your First Sass Project
The beauty of using Sass is that you can make as many small .scss
files as you see fit because they will all be combined into one master .css file during the preprocessing stage. Consider the following style.scss
file:
@import "global/mixins";
@import "global/variables";
@import "global/normalize";
@import "content/links";
@import "content/lists";
@import "content/mediaObjects";
@import "content/panels";
@import "content/spacingOverrides";
@import "content/typography";
@import "content/textUtilities";
@import "layout/border";
@import "layout/grid";
@import "layout/scaffolding";
@import "navigation/breadcrumbs";
@import "navigation/master";
@import "navigation/leftnav";
@import "navigation/topnav";
@import "navigation/pagination";
@import "navigation/tabs";
@import "navigation/footer";
@import "forms/buttons";
@import "forms/forms";
@import "tables/tables";
@import "tables/forum";
Each of those @import
statements includes a new .scss
file. When naming these component .scss
files, make sure you use an underscore (_
) character at the start of the file name.
Example: _variables.scss
, _normalize.scss
. The Sass compiler will interpret these files as snippets and won’t actually preprocess them individually. Only the files you want the preprocessor to compile should be named without an underscore, e.g., style.scss
, special-page-override.scss.
When you import the snippet files into your main style file, there’s no need to include the underscore of the file extension because Sass knows you’re working with .scss
files.
As you might have guessed, it makes total sense to organize your Sass files into folders for easy separation of logic and structure — you can get as complex as you need, but remember that everything you do will need to make some sort of sense six months down the line when you come back to modify stuff. Don’t make it more difficult for your future self (or a different developer).
Extending Sass
There are a number of excellent add-ons or frameworks built on top of Sass. But I’m going to talk about just one — the almighty Compass.
Compass
Working with Sass and Compass makes me smile. In actual fact, I’m smiling as I write about Compass and I’m hoping you will be too when you’re done with this article. Compass is a full-featured framework built on top of Sass that includes reusable patterns, sprite generation, typographic rhythms and all the CSS3 mixins you’ll ever need.
The compiling software I mentioned above will all be able to deal with Compass, so getting started with Compass is a very simple process.
Create a file in the root of your web project called config.rb
. This file will tell Sass that you’ll be using Compass for your project. The code below is the very minimun you require to get Compass going:
http_path = "/"
css_dir = "css"
sass_dir = .scss"
images_dir = "images"
javascripts_dir = "js"
fonts_dir = "fonts"
output_style = :expanded
environment = :development
Check out this Gist for an example of config.rb
file.
The next step is to import Compass into your main style file. You can either import the entire Compass framework or parts of it as and when you need them:
@import "compass";
@import "global/mixins";
Or…
@import "compass/utilities";
@import "compass/css3";
@import "compass/typography/vertical_rhythm";
@import "global/mixins";
I could blow another 5,000 words waxing lyrical about Compass as there is so much to it, but instead I’m going to dig into one of its most powerful features …
Sprite Generation with Compass
Sprites have quickly become the default standard for delivering images on the web using CSS. In short, you create one big image containing all the smaller images your page needs, thereby reducing HTTP server requests, which is good for website performance. If you’re unfamiliar with the concept, then I suggest you have a quick read about it.
Sprites are great for the web but they can very quickly become painful to maintain. I often find I have to update my sprites as a project progresses and this becomes a chore as you not only have to update your main sprite sheet but you also have to update your CSS (and potentially HTML, too).
Over the years, there have been some great tools introduced to help make this process easier, but nothing has quite sat right with me. Until now.
The main idea here is that you should create single images as you would have in the olden days. The important thing is to keep your images organised into folders, as illustrated below.
The next step is to include the required compass mixins and utils and import your images. In the following examples, I’ll be illustrating how this might work when using the images/icons
folder:
// include the compass spite utility if not already included
@import "compass/utilities/sprites";
// import your images
// note: compass already knows my images live in the /images/ folder
@import "icons/*png";
// automagically generate class names
@include all-icons-sprites;
I’ll walk you through what’s happening in the snippet above.
- The first import is importing the correct Compass sprite utils
- The next import is telling Compass where the images are that you’d like to use as a sprite
- The include line is where some magic occurs. This line will auto-generate a bunch of class names based on the name of the image folder and the name of the PNGs therein.
The generated CSS is below:
.icons-actions-add-mini,
.icons-actions-delete-mini,
[...]
.icons-multimedia-camera {
background: url('/images/icons-s34fe0604ab.png') no-repeat;
}
.icons-actions-add-mini {background-position: 0 0;}
.icons-actions-delete-mini {background-position: 0 -16px;}
[...]
.icons-multimedia-camera { background-position: 0 -96; }
Now, you could just walk away and happily use those generated classes wherever you wanted. Job done. Thanks, Compass!
However, I often find I’ll need to add my own class names — based on nested elements, perhaps. No worries. Compass allows us to do this.
Note: With the following examples, the param passed into those icons-sprite-*()
utils are the names of the .png files in your images/icons
folder.
@import "icons/*.png";
.actions {
.add { @include icons-sprite(actions-add-mini); }
.delete { @include icons-sprite(actions-delete-mini); }
}
.contact {
.mail { @include icons-sprite(contact-mail); }
.phone { @include icons-sprite(contact-phone); }
}
.some-random-class-name { @include icons-sprite(hardware-television); }
For a detailed walk-through of building sprites with Compass, head over to George Martsoukos’s article here on SitePoint.
Compass lets you make quite a few other customizations. This next example is one I find myself using quite a bit:
// making use of width/height magic selectors
.icon-giant-killer-bear {
$width: icons-sprite-width(giant-killer-bear);
$height: icons-sprite-height(giant-killer-bear);
@include icons-sprite(giant-killer-bear);
@include size($width, $height);
margin: 0 4px 0 0;
vertical-align: text-bottom;
}
The above example illustrates how quick it is to get the image dimensions of a particular image from your sprite.
I haven’t dug too deeply into all of the sprite utils, but check the Compass website for the full sprite documentation as I’m sure there are lots of other awesome things out there.
To Sum Up
There is an exciting world of front-end code out there and this is just a very small part of it. Start using Sass now! It’s made my code writing more efficient and it’s made writing CSS a lot more enjoyable.