CSS preprocessors like Sass make my job immeasurably easier, and a whole lot more fun! It makes my CSS coding faster, cleaner, and more well-thought-out.

However, despite the many advantages of Sass, I’ve noticed (and been guilty of creating) some less-than-ideal situations arising from its use. I’m still learning to fully harness the power of this young technology, and I’m sure there’s a lot more for me to learn. In the meantime, I’d like to share some common Sass pitfalls I’ve run into in recent weeks that can be easily avoided.

Avoid Sass pitfalls!

1. Selector absurdity

Nesting is one of the most time-saving features of Sass, but it can very quickly lead to problematic code. While you would (I hope) know better than to write crazy town selectors like…

…you might lose track of just how specific you’re getting as you keep following the nesting of your HTML. Next thing you know, you’re throwing !important around to override the crazy town selectors, and you lose any chance of re-using the code without a full copy-and-paste.

Many proponents of ‘pure’ semantic html may love that you can now easily get away with targeting the anchor link of the fifth child of the unordered list inside the nav element that is the direct child of the body element—but that doesn’t mean that you should! The above selector could have easily been replaced with .button, for example. I try to follow a couple rules of thumb when it comes to nesting my selectors:

  • only nest your selector if it is 100% necessary
  • avoid nesting more than 4 levels (even if it seems like a good idea at the time).
  • if you even suspect that you might re-use this style elsewhere in your project, nest it as shallowly as possible and give yourself an easy way to target it (such as a class)

2. @mixin madness

Sass mixins are incredibly useful and powerful, allowing you to avoid writing line-after-line of browser-specific CSS3, perform the complex calculations necessary for responsive designs, and do almost anything else you’d need. However, next time you’re tempted to add @include to a selector, remember what you’re actually doing: you’re essentially copying-and-pasting that code everywhere you use @include. In some cases, this is necessary: when you’re doing calculations or passing in parameters (like calculating layouts or specifying gradients), but other times, you’re just adding a lot of unnecessary repetition.

One example that I’ve seen frequently (and am guilty of using myself) is setting inline-block in a cross-browser-friendly way. I’ve seen a lot of code along the lines of:

While this might seem like a clever way to save yourself re-writing those lines of code, you’re still outputting the same thing as if you were not using the mixin:

Less than ideal. However, there is an easy (and awesome) alternative: @extend. Sass allows you to give an element the same properties as another element by using @extend. For example:

This allows you to use a .badError element (without also including the .error class) and have it inherit the same properties. How is this different from using @include? The difference is in the CSS output. Instead of including the code from .error in .badError, @extend attaches both selectors to the same rule.

If @include gives a selector a copy of the properties another selector has, @extend puts selectors in the same club so that they can all share the properties. It’s like CSS communism.

The above outputs to:

Much more efficient, no?

If we go back to our original example of setting inline-block on an element, we can use @extend to add as many selectors as we want to the ‘pool’ of inline-blocked elements.

outputs to:

Placeholders make @extend even better.

What if you don’t want to create .element? What if all your inline-block elements will also have other properties (a likely scenario)? Sass 3.2 now gives you the option to create ‘prototype’ rules using % as a placeholder. The rule is then only instantiated when it’s called using @extend. Using the inline-block example one more time:

This Sass code outputs the same CSS as the previous example. A quick rule of thumb I came across on the Sass blog:

  • if you’re making a calculation or passing in variables, use @include
  • if you’re just repeating the same rules, use @extend

3. Getting Lost

One of the downsides to using CSS preprocessors is that you lose the ability to reference line numbers from the web inspector, which may not be a huge problem if you’ve just written the code, but if you’re coming back to a project months later, or if you’re working with someone else’s code, it can get pretty frustrating to find the rule you’re looking for. My workaround usually involves running -grep -n from the command line (the -n flag outputs the line number of the matched term), but this is a tedious process and can often result in too many matches.

A better option is to take advantage of the :debug-info option in Sass using Sass Sleuth for webkit inspector, or FireSass for Firebug. To use these plugins, you need to configure Sass to output debug info, which you can do in your environment variables in rails, or you can just pass in the --debug-info flag when running Sass from the command line.


Chrome Web Inspector with Sass Sleuth

Using Sass Sleuth, you can open up the web inspector in Chrome or Safari and reference the line number in your .scss file. If you’re using Textmate or Sublime Text, you can also configure Sass Sleuth to open up that line in your text editor. Though you wouldn’t want to run Sass like this in a production environment, it definitely can speed things up during development!


As powerful as preprocessors are, they’re still very new to the world of front-end development, and like any new tool, it takes a while to develop best practices and learn which mistakes to avoid. If you’re using Sass (or Less) thoughtfully, and taking advantage of the right tools in the right ways, it can be an incredibly powerful tool to speed up development and craft better, more semantic, more modular code. It’s easy to abuse the power of these tools, however, so make sure you’re not going to give yourself (and your teammates) headaches by getting carried away!

Discover and implement your big idea with our product team

Get a Quote