I’ve been working with CSS for more than a decade and I know all too well the problem areas, primarily in browser support and development difficulties. Tools like Firebug and similar page inspectors have changed how I debug problems but as developers, we’re always seeking the more efficient route.
On paper, the ideas behind Sass and Less seem amazing. Shorten css development by using variables (for colors, etc), reduce the amount of written syntax by calling functions once, that when compiled, produce all necessary vendor prefix equivalents, and so on. By themselves, those were enough to convince me to try it.
I tried Less first, which is mainly different by the fact that it uses javascript to compile the real css. For those unwilling to add another script and process time to the client-side there are server-side solutions as well, and then there’s Sass. Sass has essentially the same features but is compiled on the server by Ruby gems.
However, when I began using these in already-live projects I discovered how painful they are. Here is a quick rundown of everything I’ve discovered about using these technologies versus hand-written CSS.
The Environment
Right out the gate, using Sass was a pain because I had absolutely no development environment for it. I had to install ruby, as well as the gems for compiling it. Firebug needs an additional plugin (and the gems need additional configuration) so that it will point you the Sass file and not the compiled css file. All of my editors/IDEs needed special plugins in order to recognize the syntax (for coloring, etc).
Now this is all install-once-and-you’re-set stuff but it still throws several additional steps into the mix when I move to new machines, etc.
Every day of work I need to ask the compiler to watch the project for changes. When I forget to do this, I get frustrated wondering where my css changes are.
The Nesting Danger
One of the benefits of sass/less is the ability to nest selectors. The sass could look like:
body {
/* ... styles ... */
header {
/* ... styles ... */
nav {
/* ... styles ... */
}
}
}
When compiled, the selector for nav becomes:
body header nav { }
The issue is that while attracting you with a nicer layout in the raw css file, it’s compelling you to build unnecessarily complex selectors. Although there are times when you need to specify the hierarchy, it’s not every time. In one project I’ve taken over, almost everything is nested this way.
It’s a performance hit to the browser because every chain becomes longer and requires a more specific application of the styles. The bigger issue is that it becomes an absolute nightmare trying to override styles. When I’m attempting to override a base style for a larger screen size I must repeat the entire selector because CSS requires that specificity.
So I’ve wound up writing selectors that look like the following:
body #main ul li a { float: none }
It creates a lot more hassle about figuring out what the exact selector needs to be, debugging it when it’s not working, and sorting through the clutter this adds.
Commit Spam
When using version control it’s very easy to suddenly see a huge amount of commit spam from the compiled css. You can bypass this by compiling the css on deployment but that’s a bit more effort. If you have development configurations in place, sass will leave a lot of comments in the compiled css referencing the original location of the sass-version. These change with every compile and if you have a thousand-line-long css files, your commit diffs will be absolutely huge, even for a one-line change.
In fact reviewing said commits will be impossible because you can’t figure out what changed in all of that mess. In order to avoid that, you need to be sure that you never commit compiled code with any development/debug info left in.
When you’re working by yourself I see more of a benefit to using these technologies but when you’re working with a team, you’re not the only one who has to do these steps. It becomes the entire team.
Conclusion
I’m ready for you tell me why I’m wrong. But in the end I have to ask if all of this work is really worth not having to write extra vendor prefixes (which we all copy/pasted anyway) and having to refer back to your notes for each rgb/hsl/hex color code? It seems like that’s a lot easier to do to me.