CSS is for Suckers. An Introduction to Sass & Compass

Sass and Compass
Mason Wendell

So you write a lot of CSS, right? I used to be like you. I'll bet you probably write enough CSS to see tons of possibilities in the code, but also maybe you pull your hair out over some of the limitations? It's ok, you can admit it. Like when you have to copy/paste code all over your stylesheets, or when you try to remember the browser prefixes and divergent syntaxes for CSS3 techniques, or how there's no help whatsoever in managing color values. Or maybe you're one of us super nerds who actually has a use for programmatic loops and logic? If you nodded for even one of those, then let me introduce you to Sass.

Sass is a meta-language on top of CSS that both provides a simpler, more elegant syntax for CSS and implements various features that are useful for creating manageable stylesheets.

When I discovered Sass, and its companion Compass some time ago I jumped right on it. Even in the earlier days of the project it solved so many of my frustrations with writing CSS. Suddenly you can set color hex's as variables and reuse them in a project. You can also refactor and reuse oft-used bits of code as "mixins". These are analogous to functions in programming languages and let you write CSS in a DRY (Don't Repeat Yourself) fashion, and create a lean, mean stylesheet that I think is easier to write and edit then old-school CSS. Plus, with Compass and you have quick access to a baked-in library of mixins, and you can easily incorporate CSS frameworks like Blueprint, 960.gs, and Susy. What's more, you can use them semantically, rather than litter your markup with presentational class names. This is very helpful in my work theming Drupal sites where it's not always quick and easy to change class names on any given element.

These tools are relatively new, so first, let's have some introductions.

Sass: Syntactically Awesome Style Sheets

As their site says, "Sass makes CSS fun again". In the most basic use, writing Sass is exactly the same as writing CSS. If you use the new SCSS syntax, all your existing CSS files are all already SCSS files. You just need to start using the new and exciting features you have available. Alternately you can write using the more terse syntax that I prefer and save valuable keystrokes.

Here are both syntaxes

scss

Notice how similar this is to writing normal CSS. We've just added some variables.

$blue: #3bbfce;
.content-navigation {
border-color: $blue;
color:
darken($blue, 9%);
}

sass

Curly braces and semicolons have been replaced with a more strict indentation-aware syntax. I personally prefer this method. It's faster to type and easy to visually scan. Both syntaxes are equally functional, so use whichever you prefer. NOTE: I'll be using the indented sass syntax in the following examples.

$blue: #3bbfce
.content-navigation
border-color: $blue
color: darken($blue, 9%)

Compiled to CSS

.content-navigation {
border-color: #3bbfce;
color: #2b9eab;
}

Installation and set up

There are many great resources to help you get set up. I'll wait while you get set up.
http://sass-lang.com/
http://sass-lang.com/download.html
http://compass-style.org/docs/

Compass

Compass is Sass's best friend. They go everywhere together. At least they do when I'm hanging out with them. Compass at the very least will run in the background and watch your project directory and compile your Sass files whenever you save some changes. That's rad and all, but there's a lot more you can do with Compass. Compass also sets up a project structure where you can incorporate various frameworks, including your own custom idiosyncratic framework if you like. Out of the proverbial box Compass comes with a number of utility mixins and the Blueprint css framework. That's a lot of firepower already, but if you want more I suggest you mosey over to Github and check out the wealth of other goodies that people are working on. 960.gs, Susy, HTML Boilerplate and a whole lot more are in store there. There are also a number of plugins you can incorporate that were written to certain specific tasks in css. Fancy Buttons provides a nice way to add progressively enhanced css buttons, and Lemonade will compile all of your png background images into a nice, tidy sprite file.

Variables

As I mentioned above you can now set variables for CSS. Really. It's almost criminal that this isn't already possible in plain CSS, because it's so simple and powerful. The first use case that everyone goes to is: "Whoa, now I don't have to remember hex numbers for all my colors! w00t!" Or something like that. That's great and all, but trust me, there's more. Like now you now have functions available that allow you to change those colors. Like this:

$my-red: #b80000
$my-dark-red: darken($red, 10%) // renders as #410101
$my-muted-red: desaturate($red, 40%) // renders as #5c1919
$my-transparent-red: transparentize($red, 0.5) // renders as rgba(115, 2, 2, 0.5)

You don't have to stop with colors, though. Sass variables can be used to store pretty much any value you need to reuse.

$vertical-margin: 24px
$horizontal-margin: $vertical-margin * 0.5
div.container
margin: $vertical-margin $horizontal-margin

// renders as:
div.container{
margin: 24px 12px;
}

Mixins

Variables are great for storing, manipulating, and reusing values. Mixins allow you to reuse whole snippets of code, and even to interject logic while doing it. This gives you reusable and flexible ways to style your markup. You'll be using mixins everywhere, but let's start by looking at humble html lists. We use lists in html almost as often as we use div's. They're versatile, and therefore are often the best semantic element for a given piece of content, be it a menu, a tag cloud, or upcoming concerts.

Let's look at the mixin for removing bullets from lists that is included with Compass.

Defining the Mixin

This is where we write the code we want to apply to multiple places
This example happens to be included with Compass but you can easily write your own.

// REMOVE BULLETS FROM A LIST
// Turn off the bullet for an element of a list
@mixin no-bullet
list-style-image: none
list-style-type: none
margin-left: 0px

// turns off the bullets for an entire list
// NOTE THAT THIS MIXIN NESTS THE PREVIOUS ONE ON

  • ELEMENTS
    @mixin no-bullets
    list-style: none
    li
    @include no-bullet

     

    Including the Mixin

    This is how you apply the mixin as you work.

    ul.my-list
    @include no-bullets

    Or you can use the shorthand syntax:

    ul.my-list
    +no-bullets

    Rendered CSS

    ul.my-list {
    list-style: none;
    }
    ul.my-list li {
    list-style-image: none;
    list-style-type: none;
    margin-left: 0px;
    }

    Mixins are also used when implementing a CSS framework in Compass. My main problem with implementing the increasingly numerous css frameworks is that in order to apply the predefined styles you need to use presentational classnames in your markup like, "span-6". I used to use them anyway in order to gain the other benefits, but it always tasted funny. Mixins are a huge part of overcoming that hurdle. Since mixins can accept arguments we can use them to calculate an element's width and other properties, and apply those properties to semantic classes. So if your CSS framework has a set of styles that make an element 6 columns wide, set a margin, and float it to the left we can now write a mixin that can be applied to any class. What's more, we can make that mixin dynamic so that it can calculate that width and margin instead of just dumbly spitting out static declarations.

    The documentation on compass-style.org is probably the best place to take a look at the code. Below is an example of how you might implement it

    sass

    #container
    +container
    &>header
    +column(6)
    &>nav
    +column(6)
    &>#central
    +column(6)
    #main
    +column(4)
    #secondary
    +column(2)
    +last
    &>#tertiary
    +column(6)
    &>footer
    +column(6)

    Rendered CSS

    It's hard to overlook just how much css you'd have to write by hand!

    #container { width: 960px; margin: 0 auto; overflow: hidden; *zoom: 1; }
    #container > header { display: inline; float: left; margin-right: 24px; width: 960px; }
    * html #container > header { overflow-x: hidden; }
    #container > nav { display: inline; float: left; margin-right: 24px; width: 960px; }
    * html #container > nav { overflow-x: hidden; }
    #container > #central { display: inline; float: left; margin-right: 24px; width: 960px; }
    * html #container > #central { overflow-x: hidden; }
    #container > #central #main { display: inline; float: left; margin-right: 24px; width: 632px; }
    * html #container > #central #main { overflow-x: hidden; }
    #container > #central #secondary { display: inline; float: left; margin-right: 24px; width: 304px; margin-right: 0; }
    * html #container > #central #secondary { overflow-x: hidden; }
    #container > #tertiary { display: inline; float: left; margin-right: 24px; width: 960px; }
    * html #container > #tertiary { overflow-x: hidden; }
    #container > footer { display: inline; float: left; margin-right: 24px; width: 960px; }
    * html #container > footer { overflow-x: hidden; }

    Extend

    @extend is the new kid on the block, having recently been developed for Sass ver 3, and honestly I've only recently started to understand it well enough to know when it's the right tool to reach for. The concept is actually pretty simple. Sometimes you write a style for an element, and then you want to apply that style to something else, but add a little more to it. For example you might have a callout, and then want to position it on the left or right of the content.

    sass

    $horizontal-margin: 18px
    $padding: 6px
    .callout
    border: 1px solid black
    padding: $padding

    .left-callout
    @extend .callout
    float: left
    margin-right: $horizontal-margin

    .right-callout
    @extend .callout
    float: right
    margin-left: $horizontal-margin

    Rendered CSS

    .callout, .left-callout, .right-callout {
    border: 1px solid black;
    padding: 6px;
    }

    .left-callout {
    float: left;
    margin-right: 18px;
    }

    .right-callout {
    float: right;
    margin-left: 18px;
    }

    Stay Sassy, San Diego

    I never want to write CSS again. I've been spoiled. Give it a try on your next project and you will be too.

Ready to get started?

Tell us about your project