A List Apart

Menu
Issue № 340

Getting Started with Sass

by Published in CSS, JavaScript, The Server Side, Workflow & Tools24 Comments

CSS’ simplicity has always been one of its defining, most welcome features. CSS style sheets are just long lists of rules, each consisting of a selector and some styles to apply. But as our websites and applications get bigger and become more complex, and target a wider range of devices and screen sizes, this simplicity—so welcome as we first started to move away from font tags and table-based layouts—has become a liability.

While some have offered proposals on how to fix CSS—adding constants or variables, for example—none have been implemented by any browser manufacturers. And even if a browser did implement a newer, better, extended CSS, it could be years before the new syntax is supported well enough in all browsers for it to make sense to use it.

Fortunately, a few years ago developers Hampton Catlin and Nathan Weizenbaum proposed a better way to maintain a complicated stylesheet. While browsers aren’t ready for a new CSS, Catlin and Weizenbaum realized they could go ahead and design a new style sheet syntax with features to help make their increasingly complex CSS easier to write and manage, then use a preprocessor (a program that runs on your computer or server) to translate the new smart syntax into the old, dumb CSS that browsers understand.

The new stylesheet syntax they developed is called Sass, which stands for “syntactically awesome style sheets.” The original versions of Sass looked very different from regular CSS; there were no curly braces, and properties had to be indented with a specific number of spaces or else the compiler would raise an error. Programmers (who are used to learning new syntaxes, and enjoy pain) didn’t mind this so much, but for regular web designers it was different enough from the CSS they knew that most of them stayed away. There was a practical issue as well: because Sass’ indented syntax wasn’t compatible with regular CSS, it was difficult for people with large existing websites to start taking advantage of it without spending time converting their old code to Sass.

So in Sass 3.0 the developers introduced a new, more CSS-like syntax called SCSS (or “Sassy CSS”). SCSS is what the nerds call a “strict superset” or “metalanguage” of regular CSS, which means anything that’s valid CSS is also valid SCSS. In other words, all of your existing style sheets should work with the Sass processor with no problems, allowing you to get your feet wet by playing with some Sass features without learning every facet of the new language.

Unlike regular CSS, Sass’ SCSS is a real scripting language, with expressions, functions, variables, conditional logic, and loops. You don’t have to use all of these features to get some benefit out of Sass, but they’re there if you need them, and on large projects they can make complex or repetitive CSS much easier to write.

For this article I’m going to demonstrate a few basic moves, to give you an idea of what’s possible with Sass and SCSS in your designer’s utility belt. At the end I’ll recommend some links and books to check out when you’re ready to explore further.

To keep things as clear and simple as possible, most of my examples below focus just on the SCSS code, not the compiled CSS output. The best way to understand how Sass works is to try it for yourself, by writing some SCSS styles and seeing what comes out. That said, all of my source code examples are available on GitHub for your reference, along with their compiled CSS output, so you can see how all of these neat new features translate into usable style sheets.

Getting started

Sass is written in Ruby, and distributed via the Ruby package manager, RubyGems. If you’re already familiar with Ruby (and your computer’s command prompt) you can find instructions for installing and running the Sass gem on the Sass website.

For those who are less handy on the command line, or who just want a fast and easy way to work with Sass, there’s Scout, an AIR app available for Mac and Windows that comes with Ruby and has the Sass compiler built in.

Both the sass command line tool and the Scout app work by watching your SCSS style sheets for changes as you work on them, then automatically compiling them into regular CSS when you save. The directory where your Sass files live is called the input folder. Your processed CSS files are saved to the output folder. These folders can be nested inside one another; in fact, a typical pattern is for the input folder (which I usually call “scss,” though you can name it whatever you like) to live inside of your site’s regular stylesheets folder, like so:

my_project/
  index.html
  css/
    main_style.css
    scss/
      main_style.scss 
      _mixins.scss
      _colors.scss

In my scss folder above, the files whose names start with underscores are called partials. As the name would imply they contain “partial” style sheets, chunks of SCSS code to be imported into one of your main SCSS files. I’ll talk more about partials in a moment, but now you know where they live.

Use partials to organize your code

CSS already provides the @import directive for linking to additional, external style sheets, and some developers like to use it to break up a large project’s styles into smaller logical chunks. For example, our main_style.css file might contain nothing but @import statements linking to a bunch of page-specific style sheets:

@import url('/shared/global.css');
@import url('/pages/home.css');
@import url('/pages/blog.css');

This isn’t considered the best practice however, because each of these imports is one more file that has to be requested and loaded by the browser, which can make your site load more slowly and will definitely lower your YSlow and Google Page Speed scores.

Sass helps out by letting you break large style sheets into partials. You still refer to them using the @import directive (in a new, briefer form), and when your SCSS files are processed, the contents of the partial are inserted directly into the output CSS. (Importing a URL works the same way it does in regular CSS.)

@import 'shared/global';
@import 'pages/home';
@import 'pages/blog';

The result is one file containing all of your styles. Sass can also automatically minify its CSS output, stripping out unnecessary white space or line breaks to optimize loading times.

There is one catch. Partials are a special kind of SCSS file, not meant to be used as regular stylesheets. Any code you put into one must be @import-ed into a stylesheet to be used. Partials’ filenames must start with an underscore—for example, the pages/home partial loaded above would actually be named pages/_home.scss. (These paths are always relative to the current file.) The underscore is how the Sass compiler knows that a file is a partial, and therefore shouldn’t be compiled into a fully-fledged CSS sheet. But given the purpose of a partial is to organize your code into logical chunks, this seems a fair trade-off.

Don’t repeat yourself

Now that our style sheets are better organized, let’s try to make them less repetitive.

One of Sass’s nicest features is nested rules. In a regular CSS file, rules must be listed sequentially, and every rule’s selector must include all of its elements:

body.home .media-unit {
  border: 1px solid #ccc;
  background-color: #fff;
}
body.home  .media-unit .right {
  border-left: 1px solid #ccc;
}
body.home .media-unit .right h1 {
  font-size: 24px;
}

Apart from being really, really repetitive, this code doesn’t do anything to help us understand how the HTML elements we’re styling relate to each other. With nesting, we can write SCSS code that is both less redundant and easier to follow:

body.home {
  .media-unit {
    border: 1px solid #ccc;
    background-color: #fff;
    .right {
      border-left: 1px solid #ccc;
      h1 {
        font-size: 24px;
      }
    }
  }
}

After processing this will result in the same CSS as above. Unfortunately, the shorter syntax won’t make your CSS files any smaller or load any faster. But nesting will help keep your code clean, logical, and well-organized, which should also make it easier to manage over time.

Another cool nesting trick: Sass allows you to nest media queries inside other rules, making it easier to see which styles are applied to a given object on your page:

.container {
  width: 940px;  // If the device is narrower than 940px, switch to 
  // a fluid layout
  @media screen and (max-width:940px) {
    width: auto;
  }
}

When processing this file, Sass knows how to convert this back into valid CSS, copying the .container selector inside the media query like so:

.container {
  width: 940px;
}@media screen and (max-width:940px) {
  .container {
    width: auto;
  }
}

Variables

Sass variables are great for two reasons. First, and most importantly, they make code easier to change by reducing duplication. But they also allow you to assign names to special property values like colors, which helps you understand the intent behind a given style.

At Typekit a number of elements in our UI use our signature green color, #99cc00, or “Typekit green” for short. This color appears hundreds of times in our CSS, used on everything from buttons to headline colors, such that if we ever changed our brand colors away from Typekit green it would be a lot of work to change every instance. By using variables instead of the raw hex code, it’s easy—just change the variable (which you can define at the top of your stylesheet, or even in a partial) and the new color appears everywhere, instantly. You can even set variables to other variables, which helps keep your style sheets semantic:

$typekit-green: "#99cc00";
$typekit-link-color: $typekit-green;a {
  color: $typekit-link-color;
}

You can assign almost any kind of value to a variable; apart from color hex values, they’re especially good for font-family stacks:

$sans-serif-font: 'ff-dagny-web-pro', 'Helvetica Neue', Arial,  
Helvetica, 'Liberation Sans', sans-serif;
$serif-font: 'ff-tisa-web-pro', Georgia, Times, serif;.banner h1 {
  font-family: $sans-serif-font;
}

Mixins

Mixins are reusable sets of properties or rules that you include, or “mix,” into other rules. You define them using the @mixin keyword, and include them using the @include keyword.

In this example, I’m telling Sass to apply all of the style properties contained in the highlighted-bold-text mixin to all of the span elements inside .result-with-highlights

$highlight-color: #ffa;@mixin highlighted-bold-text {
  font-weight: bold;
  background-color: $highlight-color;
}.result-with-highlights {
  span {
    @include highlighted-bold-text;
  }
}

Once you’ve defined a mixin, you can reuse it anywhere else in the same file. Here I’m saying that elements with a class named highlighted should also have the color and font weight properties specified by the mixin:

.highlighted {
  @include highlighted-bold-text;
}

This is really useful for applying new CSS3 properties to elements, while ensuring wide cross-browser compatibility via vendor prefixes and fallback stacks. In regular CSS, vendor fallbacks can be annoying to use because they’re so verbose, which leads to a lot of boring copy-and-pasting. Sass mixins let us use new kinds of styles in a bulletproof way without writing a lot of code.

Here I’ve defined a mixin that applies 4px rounded corners to an element, using vendor-prefixed properties for WebKit, Firefox, and IE, followed by the standard border-radius property from the CSS3 spec. I’ve also defined the corner radius as a variable so it’s easier to change later on:

@mixin rounded-corners {
  $rounded-corner-radius: 4px;
  -webkit-border-radius: $rounded-corner-radius;
  -moz-border-radius: $rounded-corner-radius;
  -ms-border-radius: $rounded-corner-radius;
  border-radius: $rounded-corner-radius;
}.button {
  @include rounded-corners;
}

Mixins can also contain whole nested rules, not just properties. Here is a version of the familiar clearfix CSS hack implemented as a Sass mixin:

@mixin clearfix {
 // For modern browsers
  &:before,
  &:after {
    content:"";
    display:table;
  }  &:after {
    clear:both;
  }  // For IE 6/7 (trigger hasLayout)
  & {
    zoom:1;
  }
}.group {
  @include clearfix;
}

The ampersand (&) selector is a Sass convention that means “this element.” When this code is compiled Sass will replace all the & symbols with the current selector, in this case .group.

Making stylesheets smarter

Using mixins to apply simple styles is cool, but what makes mixins awesome is that they can take arguments, just like a function in JavaScript or PHP. And you can use them in combination with more advanced features like expressions and functions to go far beyond organization to implement some great, complex styles.

Grid layout systems are a great application for Sass scripting. There are a lot of ready-made 960px CSS grid systems out there, but most of them require you to add non-semantic class names to your code. Not to mention the fact that to use one of these grids, you have to load all the CSS for the entire system, even if you only plan to use a few standard unit sizes.

For our final example, we’re going to implement a simple 12-unit grid in Sass. Rather than define class names for each grid unit, we’ll create a mixin that will apply the correct width and margins to turn any element into a unit of our grid.

First, we need to set up our column and gutter widths as variables:

$column-width: 60px;    // 12 columns = 720px
$gutter-width: 20px;    // 11 gutters = 220px

Next we’ll need Sass to do some math for us. A unit of our grid will span a certain number of columns, plus all of the gutters between those columns. To calculate the width, we’ll use the following formula:

width = (column width — span) + (gutter width — (span – 1))

Now we can write our mixin. Unlike the examples above, this mixin will take one argument—the span—which will be passed into our mixin as a variable. Each grid unit will be floated left, and to maintain the 20px gutter between columns, each unit will have a right margin equal to the gutter width:

@mixin grid-unit($span) {
  float: left;
  margin-right: $gutter-width;
  width: ($column-width * $span) + ($gutter-width * ($span - 1));
}

Simple, right? But there’s a lot of power in those few lines of code. We can implement a basic two-thirds layout with a main content area and a sidebar very simply, using some more semantically-named classes and our Sass mixins:

.container {
  @include clearfix;
  @include grid-unit(12);
  float: none;
  margin: 0 auto;
}.main-content {
  @include grid-unit(8);
}.sidebar {
  @include grid-unit(4);
  margin-right: 0;
}

As valuable as this is—and I use some version of this grid calculator mixin on every project I work on nowadays—this just begins to scratch the surface of what’s possible with Sass. 

Sass’ support for basic math expressions help make it much easier to craft adaptive fluid-width layouts. Here I’m using Ethan Marcotte’s responsive-width formula to create a more responsive version of my basic grid above. Sass doesn’t convert between CSS units unless specifically asked to, so I’ve wrapped my formulas in Sass’ built-in percentage() function:

.container {
// result = target / context
  width: percentage(940px / 960px);  .main-content {
    // This is nested inside of .container, so its context is 940px
    width: percentage(620px / 940px);
  }  .sidebar {
    width: percentage(300px / 940px);
  }
}

There are also functions for transforming and adjusting colors—you can make colors darker or lighter, or adjust saturation or alpha transparency, right within your style sheet:

$base-link-color: #00f;
a {
  color: $base-link-color;
}
a:visited {
  // This reduces the lightness of the color (in HSL terms) 
  // by 50%, leaving hue and saturation alone
  color: darken($base-link-color, 20%);
}figcaption {
  // Generates an rgba() color value with 50% opacity
  background-color: transparentize(#fff, 50%);
}

And if those functions aren’t enough you can define your own, and share and reuse them across projects as a simple partial. Check out the full list of built-in SassScript functions for a taste of what’s possible.

What’s next?

The official Sass website is full of useful information, including a complete reference guide to the SCSS language. One thing you may find useful right away is this list of available SCSS text editor plugins, offering syntax highlighting and other useful tools for writing Sass code in your editor of choice.

In addition, Sass creator Hampton Catlin is currently finishing up an in-depth guidebook to Sass for the Pragmatic Programmers, which you can buy and read today through Pragmatic’s Beta Books program.

Beyond the core Sass language, there’s also Compass, a library of SCSS functions and patterns developed by Chris Eppstein, with built-in support for Eric Meyer’s CSS reset, the Blueprint grid system, plus tons of CSS3 and typographic effects. Its authors have called it “jQuery for stylesheets,” which is a pretty apt description. If you’re using the Scout app, the Compass framework is already installed. Otherwise, you can find instructions for installing and using it on the Compass website.

24 Reader Comments

Load Comments