Leveraging the power of Sass

Roughly a 7 minute read by Admin

Sass has, amongst other CSS pre-processors, seen a huge rise in popularity over the last year, with many front end developers yearning for easier to maintain and produce stylesheets.

And while it's debatable whether pre-processors actually produce less or more efficient code, (really, it's still in the hands of the developer), they certainly help remove some of the mundanities of writing everyday CSS.

This tutorial will go over some intermediate uses of Sass; hopefully showing you how to implement some of its lesser used functionality. By the end of this tutorial, you'll have used placeholders, variables, interpolation and the @mixin, @content and @extend directives.

The situation

Our hypothetical situation will be displaying an icon sprite, and while the solution may be over-engineered, it's geared to show as many different aspects of Sass as possible.

You can download the icon sprite here. It contains 6 icons (two different sizes split in to two columns), which are taken from Fat Cow and are free to download.

We want to be able to add new icons to the project using simple and succinct code. Like this:

@include icon_small('batman', 1);
<span class="icon_batman"></span>

Which should produce something along the lines of this:

The code

I'll be assuming you are comfortable with Sass, and that you already have a system in place to compile it into CSS. The code will be written in the .scss syntax, but it shouldn't be too hard to convert into .sass syntax if you're that way inclined. I'll also be assuming you support IE8 and above.

Base icon class

Because we have two sizes of icons, we need two base classes. We'll never use these classes in our HTML, we'll simply use Sass's @extend functionality so our individual classes inherit their styles.

%icon {
    background: url(../img/icons.png) left top no-repeat;
    content: '';
    display: inline-block;
    height: 16px;
    vertical-align: middle;
    width: 16px;
}

%icon_large {
    height: 32px;
    width: 32px;
}

We're using the @extend only placeholder, %, so we never actually compile a class called .icon/.icon_large. This means we can still create an .icon/.icon_large class if we want to. Also, notice we don't extend the .icon class in the .icon_large class. This will become apparent why later.

Icon @mixin

@mixins are very useful in cutting down the amount of CSS you write.

First, we need a core icon @mixin.

// Base icon @mixin, pass in the icon name, the x position
// and the y position of the background (in pixels, and both default to 0)
@mixin icon($name, $x : 0, $y : 0) {
    // Create the actual unique item class
    .icon_#{$name}:before {
        // Inherit our base icon class
        @extend %icon;
        // Set the unique background position
        background-position: #{$x}px #{$y}px;
        // Pass in any other unique styles we want
        @content;
    }
}

We've placed our icon code in the :before pseudo selector so we can still use the actual icon element to place a background image/colour behind our icon if we want to.

We've also used interpolation to include the icon name in the class. You must use this when mixing pure CSS with variables.

@content note

The @content directive simply includes any additional styles we may have included. So if, for instance, we did call our icon mixin directly, we could do this:

@include icon('icon_name') {
    border: 1px solid red;
}

Which would compile to:

.icon_icon_name:before {
    // Styles inherited from the %icon class
}

.icon_icon_name:before {
    background-position: 0px 0px;
    // Styles from our @content directive
    border: 1px solid red;
}

Icon @mixin helpers

While we could just use the icon @mixin, we can make it even simpler when defining our icon by creating helper @mixins, which will do some heavy lifting for us. We'll create a helper @mixin per icon size, allowing us to:

  • Separate out any icon size specific code into its own @mixin.
  • Work out the background position by simply passing in a row number.
// Icons sizes
$icon_base: 16;
$icon_base_large: $icon_base * 2;

// Small icon @mixin, pass in the icon name and the
// background y position (the number row it's on, not in pixels)
@mixin icon_small($name, $y) {
    // Get the correct y position in pixels
    $y : ($y * $icon_base) - $icon_base;
    // Include our base icon @mixin
    @include icon($name, 0, -$y);
}

// Large icon @mixin, pass in the icon name and the
// background y position (the number row it's on, not in pixels)
@mixin icon_large($name, $y) {
    // Get the correct y position in pixels
    $y : ($y * $icon_base_large) - $icon_base_large;
    // Include our base icon @mixin
    @include icon($name, -$icon_base, -$y);
    // Also inherit our large icon class
    .icon_#{$name}:before {
        @extend %icon_large;
    }
}

We also define a few variables at the top here, which are simply for both our icon sizes. We could hardcode them, but using variables makes it much easier to change the values if we wanted to move this to a different site. (Generally, these variables will be placed at the top of your file, or in a settings file.)

Defining our icons

Now for the easy part: actually defining our individual icons. Because we've done all the groundwork above, this couldn't be easier!

// Small icons
@include icon_small('batman', 1);
@include icon_small('ninja', 2);
@include icon_small('terminator', 3);
@include icon_small('spiderman', 4);

// Large icons
@include icon_large('pirate', 1);
@include icon_large('panda', 2);

And that's it! Whenever you add a new icon, simple add a new @include with the name of the icon and what row it's on.

For any icon specific code, don't forget about the @content directive we placed earlier:

@include icon_small('batman', 1) {
    // Icon specific code here
}

Displaying the icons

To display the icons, simply apply their class to an element like so:

<span class="icon_batman"></span>
<span class="icon_spiderman"></span>

You can technically use any element you want, but I think a span fits nicely. Depending on what element you use, you may need to adjust the padding/margin value to remove any defaults.

Improvements and gotchas

With a lot of these implementations, the code may seem overly complicated at first, especially if you're not from a development background. Therefore, it's always important to comment the code thoroughly! Looking back in 6 months, comments could be the difference between easily editing the code, and spending valuable time figuring out what you've done.

We can go even further with this example, too. For instance, we could create a list of icons, which we loop through, automatically creating our individual classes. However, this can overcomplicate the code and is generally unnecessary; the difference in work between adding a name to a list, and adding a new include line is negligible.

Wrap up

That concludes the tutorial. Again, you can download the files and pick apart the code if you want.

If you have any issues, improvements, questions or want to let us know any useful Sass tricks, leave us a comment!