CSS Preprocessing

Outline

What is a CSS Preprocessing?

CSS Preprocessors allow you to write in css-like languages that are then compiled to plain old CSS. These css-like languages extend css with support for things like variables, mixins, math operations, color operations, and more. In general they just make CSS a lot easier to write, and a lot more maintainable.

There are many CSS Preprocessors available, two of the most popular are LESS and SASS. There is much debate over which is better. In all the following examples, I'll be using the scss syntax of SASS because I think it's syntax is clearer for explanatory purposes. Many of the features outlined below are supported by all major CSS Preprocessors, though the syntax may be different.

Benefits of CSS Preprocessing

  • easier to read
  • more maintainable
  • faster to write

Variables

$brand_color: #019bc6;
$padding: 10px;

.myClass {
    background-color: $brand_color;
    padding: $padding;
}

.anotherClass {
    padding: $padding;
}

Variables can also be interpolated:

$attr: background;
div {
  #{$attr}-color: blue;
}

Operations & Functions

SASS supports many different kinds of math operations, and is generally intelligent about the resulting units:

$nav_height:     80px;
$top_padding:    $nav_height + 20px;

$nav_width:      100%;
$num_sections:   4;
$section_width:  $nav_width/$num_sections;

SASS has functions to make working with colors easier:

$brand_color:    #019bc6;
$light_accent:   lighten($brand_color, 10%);
$dark_accent:    darken($brand_color, 8%);
$brand_compl:    compliment($brand_color);
$desaturated:    desaturate($brand_color, 20%);

SASS also has a number of utility functions, such as round, floor, ceil, abs, min, and max.

Mixins

Mixins allow you to easily reuse chunks of css:

@mixin noise_background {
    background-color: #ededed;
    background-image: url("images/noise_texture.png");
}

section {
    @include noise_background;
    border: 1px solid #ccc;
}

table {
    @include noise_background;
    width: 100%;
}

Mixins can also take paramterrs. This is especially useful when creating mixins for vendor-specific prefixes:

@mixin rounded_corners($radius) {
    -webkit-border-radius: $radius;
    -moz-border-radius: $radius;
    border-radius: $radius;
}

.foo {
    @include rounded_corners(4px)
}

Mixins can even include other mixins:

@mixin rounded_noise_bg($radius) {
    @include noise_background;
    @include rounded_corners($radius);
}

This doesn't even begin to scratch the surface of what is possible with mixins. See the documentation for more details.

Nesting Selectors

SASS and other preprocessors allow you to write descendant selectors by nesting them inside other selectors. Not only does this make CSS files much easier to read, but it also makes them much more maintainable. This is probably the feature of CSS Preprocessors you will find yourself using most. Here's what it looks like:

/* SASS */
.photoSection {
    width: 100%;
    background-color: white;

    a {
        border: 2px solid white;
        display: inline-block;
        margin: 5px;

        img {
            width: 100px;
        }
    }

    span, h1 {
        font-weight: bold;
    }
}

The above would produce the following when compiled to CSS:

/* CSS */
.photoSection {
    width: 100%;
    background-color: white;
}

.photoSection a {
    border: 2px solid white;
    display: inline-block;
    margin: 5px;
}

.photoSection a img {
    width: 100px;
}

.photoSection span {
    font-weight: bold;
}

.photoSection h1 {
    font-weight: bold;
}

In addition to providing a shortcut for descendant selectors, nesting also allows you to concatenate things directly to the selector:

a {
    color: blue;

    &:hover {
        color: lighten(blue, 10%);
    }

    &:before, &:after {
        content: "--";
        color: #cccccc;
    }
}

Inheritance

Inheritance allows us to duplicate styles from another selector without rewriting them:

.error {
    color: red;
    background-color: lighten(red, 80%);
}

.errorTooltip {
    @extend .error;
    height: 40px;
    @include rounded_corners(4px);
}

.errorModal {
    @extend .error;
    @include rounded_corners(6px);
    width: 300px;
}

Currently, many developers accomplish this kind of modularity in their stylesheets through careful structuring of classes.

Choosing a Preprocessor

The question of which css preprocessor to use is one that is highly debated. Ultimately, I think SASS is probably the best option at the moment, but development on LESS has been very active lately (more than SASS) so this may change soon. For a more detailed comparison see the link below:
http://css-tricks.com/sass-vs-less/

For the majority of projects any preprocessor will suffice. Use whatever you are most comfortable with, or maybe consider trying a preprocessor you haven't used before if you feel like experimenting.

(There's another preprocessor called Stylus that I know Chris will want me to mention. I haven't used it, and can't comment on it's capabilities.)

Here's a recent survey regarding usage and preference of preprocessors:
http://css-tricks.com/poll-results-popularity-of-css-preprocessors/

Libraries

One of the biggest factors in choosing a CSS Preprocessor are the libraries that are available for it. In this case, "libraries" refers to sets of common mixins that you can import into your project and use immediately. Often, these mixins will abstract away browser differences, or provide convenient syntax for complicated featurs of CSS.

For SASS, there's Compass For LESS, there's LESSHat, and LESS Elements.

Compass (for SASS) is pretty full-featured, but a bit nebulous and harder to use.
LESS Elements (for LESS) is compact, and very easy to use, but only covers the most commonly used mixins.
I haven't personally used LESSHat, but supposedly it's more full-featured than LESS Elements.

Resources

Misc Links

SASS vs LESS vs Stylus
Less Compilation

Try CSS Preprocessing in the browser! (no installation required)

You can try LESS or SASS in the browser with no installation at CodePen. You can try Stylus in the browser at the Stylus website.