Gettin’ Sass-y

This is a repost of an article I wrote for the K-State OME web team blog.

At OME, I’ve been pushing Sass for a while. Recently, I asked some local web developers/designers on Twitter whether or not they use Sass. All of them said no. A few of them said they wanted to try it, but just hadn’t yet. Others were reluctant to add a pre-processor to their workflow. All of their reasons are understandable, but here’s why they (and you) should consider adding it to their workflow.

Sass?

Syntactically Awesome Stylesheets (Sass) is a CSS “pre-processor.” Or in their own words: “Sass is a meta-language on top of CSS that’s used to describe the style of a document cleanly and structurally, with more power than flat CSS allows. Sass both provides a simpler, more elegant syntax for CSS and implements various features that are useful for creating manageable stylesheets.”

There are two Sass syntaxes: .scss and .sass; .sass is the original and the one I’ll be using. .Scss is the newest style and is very similar to standard CSS – it’s good for learning Sass, but you lose some of benefits – namely, formatting.

Output

Being able to change the output of the CSS file is a reason in itself that I’d use Sass. Internally we often debate how to organize CSS files; hint: most of us prefer one-line (*cough* Derek *cough*). With Sass that doesn’t matter. Even better, you can change the output depending on the environment. Need something readable for development? Not a problem. Need to conserve bandwidth in production? Not an issue.

When you’re writing .sass syntax, it looks something like this:

body
    background: #000
    color: #fff
    font: small/1.5 Arial, sans-serif

Note the complete lack of brackets and semi-colons. Yes, that excites me – I’m weird like that.

Independent of the syntax, you can determine the output when you compile. The top is how you’d compile Sass*, and below is the CSS output.

Nested, aka Pico

sass --watch style.sass:style.css --style nested
body {
    background: black;
    color: white;
    font: small/1.5 Arial, sans-serif; }

Note: I’m honestly not sure why compiling changes colors to keyword values. I need to investigate this a bit more.

Expanded, aka default

sass --watch style.sass:style.css --style expanded
body {
    background: black;
    color: white;
    font: small/1.5 Arial, sans-serif;
}

Compact, aka one-line

Note: this is what I prefer, and would recommend for development if you’re used to one-line. It’s also what I’ll use for examples beyond this section.

sass --watch style.sass:style.css --style compact
body { background: black; color: white; font: small/1.5 Arial, sans-serif; }

Compressed, aka not human readable

Note: if you’re concerned about bandwidth or page speed, I’d recommend this for production. Also, one line isn’t a good indication of how unreadable it truly is.

sass --watch style.sass:style.css --style compressed
body{background:black;color:white;font:small/1.5 Arial,sans-serif}

Of course this can be accomplished with other programs or build scripts, but this ability alone drew me into Sass. Definitely read the docs for more information because the output affects nested styles as well.

*Compiling Sass

If you’re using the command line to compile Sass, you can basically do it in two ways: compile when you’re ready to, or use the –watch flag to compile every time there is a change to the Sass file. Personally, I like to being able to see every change I made and I’m a refreshaholic so I use –watch. If you don’t include the –style flag, it will default to :nested.

Nesting

Another one of my favorite aspects of Sass is nesting. When defining styles for a section (generic word), you often have to repeat yourself; this becomes repetitive and cumbersome. Nesting allows you to define styles within a selector without having to repeat the parent selector. A simple example:

header
    background: #fff url(assets/images/header-bkgrd.png) no-repeat 0 0
    > a
        background: transparent url(assets/images/header-logo.png) no-repeat 0 0
        display: block
        text-indent: -999em

With compact, this would be compiled to: (line breaks marked with »)

header { background: white url(assets/images/header-bkgrd.png) no-repeat 0 0; }
header > a { background: transparent url(assets/images/header-logo.png) no-repeat 0 0; display: block; text-indent: -999em; }

Sometimes you might want to reference the parent selector, which is easy to do with &.

a
    color: #fff
    text-decoration: none
    &:active, &:focus, &:hover
        color: #000
        text-decoration: underline
    &:visited
        color: #f00
a { color: white; text-decoration: none; }
a:active, a:focus, a:hover { color: black; text-decoration: underline; }
a:visited { color: red; }

Nesting is powerful, and rather essential to Sass, but I often find myself over relying on it. This can create less efficient CSS rules.

header
    background: #fff url(assets/images/header-bkgrd.png) no-repeat 0 0
    > a
        background: transparent url(assets/images/header-logo.png) no-repeat 0 0
        display: block
        text-indent: -999em
    #something
        float: left
header { background: white url(assets/images/header-bkgrd.png) no-repeat 0 0; }
header > a { background: transparent url(assets/images/header-logo.png) no-repeat 0 0; display: block; text-indent: -999em; }
header #something { float: left; }

This example isn’t a horrible offender, but there’s probably very little reason that #something needs to be nested under header – it adds more specificity for no reason (also descendant selectors are bad, mmmkay.) However, if this happens repeatedly it can result in very inefficient rules. If you end up with something like: header > nav > ul > li > a#something then you should probably re-examine how deep you’re nesting.

Variables

Variables are short and sweet. How many times do you set a property throughout your stylesheet to the same value? I’m guessing a lot…I know I do. For instance, say you need to use the reuse the K-State purple, and just to make it more difficult, you have to do this across several stylesheets. With Sass that’s really easy. You could assign a variable like $KSU_purple: #512888 – once that is defined you can use it across several imported stylesheets.

$KSU_purple: #512888

header
    background-color: $KSU_purple

a
    &:visited
        color: $KSU_purple
header { background-color: #512888; }
a:visited { color: #512888; }

Importing

With Sass’s @import you can import several stylesheets within a single stylesheet. Sure, you can do this with CSS, so what’s the big deal? The difference is if you import another Sass file it combines into one stylesheet when compiled. Certainly an easy way to reduce HTTP requests. If you need to, you can import files with the .css extension and they will be imported like normal. However, importing CSS files is no longer best practice because it has performance issues.

Typically, I at least import a reset, but imagine if you have several stylesheets (reset, grid, typography, forms) you could easily compile them into one file:

@import reset.sass
@import 960.sass
@import type.sass
@import forms.sass

Of course, you’ll have to take into account when it’s better to add another HTTP request than include unused styles across several pages.

Mixins

The last feature that I’m going to cover, but certainly not the least nor the last feature of Sass, is mixins. The Sass docs can explain it better than I can: “Mixins allow you to define styles that can be re-used throughout the stylesheet without needing to resort to non-semantic classes like .float-left. Mixins can also contain full CSS rules, and anything else allowed elsewhere in a Sass document. They can even take arguments which allows you to produce a wide variety of styles with very few mixins.”

I often use mixins for vendor-prefixes.

The mixins

@mixin border-radius($rad)
    -moz-border-radius: $rad
    -webkit-border-radius: $rad
    border-radius: $rad
@mixin box-shadow($x, $y, $blur, $color)
    -moz-box-shadow: $x $y $blur $color 
    -webkit-box-shadow: $x $y $blur $color 
    box-shadow: $x $y $blur $color

How’d they be used

header
    @include border-radius(10px)
    @include box-shadow(3px, 3px, 3px, #ccc)

Output

header { -moz-border-radius: 10px; -webkit-border-radius: 10px; border-radius: 10px; -moz-box-shadow: 3px 3px 3px #cccccc; -webkit-box-shadow: 3px 3px 3px #cccccc; box-shadow: 3px 3px 3px #cccccc; }

Handy, right? Mixins are very powerful and can be used for a variety of different things. Compass has a lot of useful mixins, I’d recommend checking it out.

All that glitters is not gold

Using Sass as development tool does come with a few “problems” that need to be worked out.

Dependency

Using Sass obviously adds another dependency in the development process. It’s certainly not difficult to learn but it is an obstacle if everybody on the team isn’t used to it. Getting everybody on board with only editing Sass files and not CSS files is also something that has to be clear. I’m sure they wouldn’t appreciate editing a CSS file only to have all their changes overwritten the next time Sass is compiled. Speaking of compiling, that can be problematic too. Ruby is a requirement of Sass. Depending on how you compile, it’s not too much of a problem to solve – even on Windows machines. At OME we’re starting to use more local development, so I usually develop and compile locally, and then move the files wherever they need to go. If you’re wanting to compile on the server, I’m not sure the best way to accomplish that. Unless you’re using Ruby on Rails or another Ruby framework, you’ll probably have to do some work arounds to accomplish it. I believe there are certain Django asset managers that will do it for you as well, but I don’t have experience with them. If you’re using .NET or PHP, then stop reading this and make some other changes. 🙂

Less efficient CSS

This isn’t a problem with Sass per se, but is more of an issue getting used to it. Earlier, I briefly mentioned how nesting can sometimes cause me to write less efficient CSS. I also tend to think about how to do things in Sass instead of the underlying CSS, which can make things a bit more complicated then they have to be. These problems can easily be fixed if you’re aware of it, and don’t get carried away. Sass is another tool to aid in development, and should not dictate your development.

TL;DR

Sass is a powerful tool with many benefits that can aid with CSS development. You should really look into adding it to your development stack.