Sass & Compass: Why The Hate?
Ever since CSS was officially introduced in the mid 1990s the way we write it has essentially remained unchanged. Yes, we’ve seen the occasional addition of new styling options and, sure, we’ve learned new ways to organize our code. But despite all the advances in web technologies over the years the limitations of CSS have always been with us.
And there’s a good reason for this. To fundamentally change the way CSS works would require the cooperation of the World Wide Web Consortium, browser makers, and developers to reach consensus and embrace new features. Given the glacial pace (or at least if feels that way) of HTML5 adoption there’s little reason to think we’ll be writing native CSS with variables anytime soon.
Turns out it’s already happened, sort of. Similar to the way developers use programming languages to generate valid HTML, Sass and its first cousin, Compass, combine to provide a powerful toolbox for generating valid CSS. It’s a win-win: developers can now use features like variables to write faster and more easily maintained code and the resulting CSS will work in browsers exactly as before. What’s not to love?
Well, this is the Internet and some people don’t love it. Rather than write another overview of the most advertised features of Sass, I thought I’d address a few of its critics and provide some tips for those still unsure about using it.
Hate 1: “It Creates Bloat, Slows the Website”
In the post The Problem with CSS Pre-Processors the author, Miller Medeiros, raises a common complaint about Sass causing bloat, concluding, “file size will increase a lot … if not used with care” and adds “the amount of duplicated code will be unacceptable (by my standards).” This raises at least two issues: how best to use Sass and what impact repeated code actually has on overall performance and file size.
A Little Perspective
When I first started learning print design I was entranced by all the fonts I could use. Those early layouts were riddled with crazy serifs and sans and goofy typefaces all thrown together in a cluttered mess. It was as if a bomb had gone off in a font foundry. It was hideous.
It seems like a similar instinct kicks in for new users of Sass. Once you’re introduced to the power of mixins and @extend it’s easy to start using them in lots of situations, sometimes where they are not needed, and the result can be needlessly repeated code. Given our awareness of how detrimental slow page-performance can be, thanks in large part to Steve Souders and the Yahoo! Exceptional Performance team, we should consider Medeiros’ file size concerns.
As a general rule, your average stylesheet will increase by ~3k for every 100 lines of uncompressed code. The single ~700-line Sass-generated CSS file for this site — warts and all (i.e., repeated code blocks) — is ~22k uncompressed; minified and compressed: 4k. Even if I inadvertently added another 1300 lines of wasted code on top of this, bringing the file to 2000 lines, the minified and compressed version would still only be about 5k. Take a look at these numbers in Figure 1.
Single CSS File Line Length | Uncompressed Size (k) | Minified & Deflate Size (k) |
---|---|---|
700 | 22 | 4 |
2,000 | 58 | 5 |
10,000 | 294 | 10 |
I appreciate Medeiros’ concern, and it is a mental adjustment letting a processor “write” your CSS, but at the end of the day the gains in productivity and code organization I’ve experienced by using Sass far outweigh any potential increase in CSS file size. If you’re adhering to best practices, and you’re not too crazy with nested selectors or otherwise overusing Sass features, then file size bloat and selector performance are non-issues.
Hate 2: “It’s Hard to Maintain and Debug”
Described by one blog as “an excellent case in the argument against CSS pre-processors”, Lea Verou confidently describes her issues with CSS preprocessors despite her own admission that she’s had “no hand’s on experience with them.”
Among her criticisms, Verou warns that coming changes to official CSS, happening “in as little as 6 years” will result in a situation where “all the code written for today’s preprocessors will eventually have to be rewritten.” Although she acknowledges CSS preprocessors can be beneficial if in the right hands, her evaluation seems to betray a fundamental misconception of Sass and Compass.
Staying Up to Date
One of the major advantages of mixins is that it allows you write a chunk of code that, without Sass and Compass, would likely require you to re-write it multiple times. Take this CSS, for example:
-webkit-border-bottom-right-radius: 5px;
-webkit-border-bottom-left-radius: 5px;
-moz-border-radius-bottomright: 5px;
-moz-border-radius-bottomleft: 5px;
border-bottom-right-radius: 5px;
border-bottom-left-radius: 5px;
If you’re writing standard CSS, each time you want to create new border-radius values you will have to include the vendor prefixes. It’s tedious. That or write each variant once and use that non-semantic class all over you HTML. Neither is desirable and both difficult to maintain.
With Sass, mixins you’ve authored only need to be updated in one place and you’re done. With Compass, when new CSS features become more widely supported (e.g., Flexbox) updates to Compass will include that new code, essentially rewriting the mixins for you. You can forget about vendor prefixes. Revising outdated CSS with all the fresh goodness requires one rebuild, taking milliseconds. So even if Verou’s CSS-preprocessor doomsday scenario comes true six years from now I’m reasonably confident the authors of Sass and Compass will figure it out.
And there’s another important part of code maintenance that Sass provides: “partials”. They liberate your code to be divided up into discreet, well-organized mini-stylesheets that get imported by other Sass files. This is particularly helpful when you have multiple team members editing the same code base. Would you prefer to share responsibility for a CSS file like the one on Verou’s site (one of five) with inline comments dividing up 1300 lines of code, or a handful of small partials named “_menu.scss” and “_header.scss” filed inside semantically named directories that further inform the structure of the site?
Show Me the Source!
Verou also cites the problem of debugging, saying, “the CSS you see in Web Inspectors … is not the CSS you wrote … line numbers don’t match any more and the CSS itself is different.”
This one’s easy. With Sass you have a number of configuration options for the compiled CSS. By default — and this is the output style to use during development — the stylesheet will print a comment above each selector containing the line number and the source file it originated in. In the Web Inspector you’ll first see information about a given selector as it appears in the compiled CSS file which, and as Verou correctly points out, isn’t what you want. But by clicking the link to the right of selector you’ll see the code you need:
/* line 12, /public/docs/scss/common/_headings.scss */
h2 {
font: normal 24px/26px Georgia, Times, serif;
margin-bottom: 10px;
margin-left: -15px;
}
When you’re ready to deploy to production you can enable the output style in the config.rb file best suited to your needs. Just the act of editing this file will trigger another build and your generated CSS will instantly reflect the change.
Hate 3: “OOCSS (or Insert Other CSS Methodology Here) Is a Better Way to Write CSS”
Blake Haswell, in his blog entry, LESS Sass. More OOCSS. writes that “Sass’s features are unnecessary” and that relying on Object Oriented CSS (OOCSS) would produce better code, implying that Sass and OOCSS are somehow mutually exclusive.
If you start using Sass, renamed your .css files to .scss, and do nothing else but run the processor over your existing OOCSS the resulting code would be identical. No difference. But let’s go one step further and consider an example from Haswell’s site:
.navigation a:hover { color: #df0000; }
.entry-meta a:hover { color: #df0000; }
The color #df0000 is defined seven times. But defined only twice it already violates the DRY principle, a previously unavoidable situation in CSS but one that can now be addressed with Sass. Granted, some repetition in CSS is fine, but he can make it easier on himself:
$color-hover: #B57EFF;
.navigation a:hover { color: $color-hover; }
.entry-meta a:hover { color: $color-hover; }
By adding a single variable the code is already easier to maintain (Google famously tested 41 shades of blue), more semantic, and the resulting CSS file is, like before, completely identical to the original OOCSS code.
There are valid reasons not to use Sass. Maybe the code you’re working with is very simple, or you’re passing it off to another developer, or you are new to CSS. But rejecting it with the claim that it will get in the way of OOCSS, or any other CSS approach, is to misunderstand what Sass actually does.
My Advice: If You Want to Learn Sass, Start By Not Using Sass
What I mean is that if you share the concerns addressed above or are otherwise unconvinced that Sass and Compass is for you, try it without using its most advertised features. Skip the variables, mixins, and its other programmatic options and just write old-school CSS. You’ll still discover many useful features. Among my favorites:
Validation. How many times have you found yourself staring blankly at your website, wondering why your CSS is only being partially applied, only to eventually find the misspelled property, orphaned bracket, or missing semicolon in your code? It’s an easy mistake to make and tracking down the problem is an unrewarding waste of time. With Sass if you make a coding error like this it will let you know what the problem is and exactly where it occurred.
Partials. Having to code in long files is a drag and breaking them into multiple stylesheets is bad for performance. Sass completely frees you to divide up your code intelligently into as many files and directories as you like and recombine them as you need. My general rule of thumb on all but very complicated sites is that if I have to scroll through a Sass file (around 100 lines of code) it’s probably too big and I should consider dividing it up.
Comments. CSS comments are publicly viewable so you may be hesitant to add too much information. Sass comments don’t make it to the CSS — they are removed during the build process — so you can, and should, add detailed documentation about your code. It will help fellow developers, and your future self, to better understand the decisions you made.
Image Sprites. Because the number one rule of page performance is to reduce HTTP calls, if your website uses repeated icons and other small graphics you’ll want to make a sprite. Anyone who’s tried to manage them manually knows how time-consuming it can be: if you no longer want an icon or need to add more white space, recreating that sprite and rewriting the accompanying code is laborious. Compass removes all that. Simply drop your images into a directory and in a few lines of code your sprite will be created, and easily updated, along with the code you need to reference it.
Sass is not a replacement for CSS, it’s more like having a CSS assistant who will help you write your code. So when you’re ready to really put it to work I recommend occasional sanity checks on the resulting CSS to see if this “assistant” has created too much repeated code or if the selectors are getting too complicated. Refactoring your Sass will help keep your code clean and you’ll start learning how you can make the best use of it.
Lastly, if you don’t want to use the command line for running the “watch” process, check out LiveReload or Compass.app. These guys sit unobtrusively in your menu bar and do the processing for you. LiveReload can monitor multiple projects so you can set it and forget it. As a bonus, with the help of a browser extension, either can be enabled to refresh the browser for you after each coding change. No more “command-r”. Very, very nice.