CSS preprocessors like LESS and Sass are very popular at the moment, being touted as valuable time-savers for front-end developers. They provide features like variables, mixins, colour manipulation, and the ability to nest CSS rules. These features sound like great additions to CSS that could boost productivity, make CSS easier to maintain, and reduce repetition.
Indeed these features sounded so great that I used Sass in a recent project. Having reflected on that project though I have found that Sass’s features are unnecessary and won’t actually help you to write better code. If you want to write better code then the key is to write plain old CSS and use the principles described as Object Oriented CSS (OOCSS).
What is OOCSS?
OOCSS is an approach to writing CSS that results in smaller more focused classes which allow much more efficient code re-use. The two main principles of OOCSS are that you should separate structure and skin, and that you should separate container and content. If you’re not sure what OOCSS is about please read these great resources and then come back:
Features CSS Doesn’t Need
Variables
Variables allow you to specify widely used values in a single place and the re-use them throughout a stylesheet.
Sounds great, right?
No.
If you write your CSS correctly there should be no “widely used values” in your code. property: value pairs should not be repeated in your code. If you need to use variables then it is a sign that your code isn’t structured correctly.
Take the following Sass code:
$small: 12px;
.sidebar {
background: #ccc;
font-size: $small;
}
.permalink {
border-top: 1px solid #ccc;
color: #333;
font-size: $small;
}
<div class="sidebar"></div>
<div class="permalink"></div>
The value 12px is used a number of times throughout the code, so we’ve taken that value and stored it as a variable. That way when we need to change the value we only need to change the value in a single place. We could do the same thing using CSS just by creating a new .small class:
.small {
font-size: 12px;
}
.sidebar {
background: #ccc;
}
.permalink {
border-top: 1px solid #ccc;
color: #333;
}
<div class="sidebar small"></div>
<div class="permalink small"></div>
This doesn’t seem like much of an improvement. But what if you want the comment count to appear small too? If you do this using your variable in Sass you’ll need to add another class:
$small: 12px;
.sidebar {
background: #ccc;
font-size: $small;
}
.permalink {
border-top: 1px solid #ccc;
color: #333;
font-size: $small;
}
.comment-count {
font-size: $small;
}
<div class="comment-count">3 comments</div>
Now, if you had created a specific .small class you wouldn’t actually need to modify your CSS at all. You could just use the existing rules.
.small {
font-size: 12px;
}
.sidebar {
background: #ccc;
}
.permalink {
border-top: 1px solid #ccc;
color: #333;
}
<div class="small">3 comments</div>
As you can see, if you need to use variables then your CSS is only going to get more and more complicated over time. However, if you use smaller classes to reduce the repetition of property: value pairs then your CSS becomes more flexible and less likely to grow out of control.
Mixins
Mixins allow you to embed all the properties of a class into another class by simply including the class name as one of its properties. It’s just like variables, but for whole classes.
Like variables, mixins are unnecessary. If you need to use them it is a sign that your code is not structured correctly. Take the following Sass example for styling some buttons:
@mixin button($background: #333, $size: 16px) {
background: $background;
border-radius: 3px;
color: #fff;
display: inline-block;
font-size: $size;
font-weight: bold;
padding: 10px;
}
.button {
@include button;
}
.submit-button {
@include button(#0f0);
}
.small-button {
@include button(#333, 12px);
}
.small-submit-button {
@include button(#0f0, 12px);
}
<button class="button">Ordinary Button</button>
<button class="submit-button">Submit button</button>
<button class="small-button">Small button</button>
<button class="small-submit-button">Small submit button</button>
And then here is the same thing written using CSS:
.small {
font-size: 12px;
}
.button {
background: #333;
border-radius: 3px;
color: #fff;
display: inline-block;
font-size: 16px;
font-weight: bold;
padding: 10px;
}
.submit-button {
background: #0f0;
}
<button class="button">Ordinary Button</button>
<button class="button submit-button">Submit button</button>
<button class="button small">Small button</button>
<button class="button submit-button small">Small submit button</button>
In this example the pure CSS is smaller, easier to understand, and easier to maintain.
As you can see, by structuring your CSS correctly you can actually write much more terse code than you would using features like variables and mixins.
Advanced Features
Sass and LESS also have several advanced features such as mathematics and color manipulation. These features do have some benefits in terms of documenting your thought process in terms of design decisions, but if you want to document your thought process the real solution isn’t to throw mathematics or function calls into your CSS, but instead to use comments.
.nav {
margin-bottom: $vertical-rhythm * 2;
}
.nav {
margin-bottom: 36px; /* Twice the line-height of body text */
}
Problems
Setting up a Development Environment
Unlike CSS which works out of the box with any text editor or browser development tools, if you want to use a CSS preprocessor you will need to download some additional tools to get your development environment working. I haven’t found a text editor that plays nicely with Sass out of the box, and you also need to download a Firebug plugin to get Firebug looking at the correct files too.
This isn’t a huge problem, but when you’ve got to setup a development environment for a team of front-end developers, it’s just more steps that need to be documented and carried out to make sure everyone is able to work effectively.
The Problem with Preprocessors
This sounds basic, but I had a couple of problems where I’d make changes in my Sass files and the CSS rules weren’t being applied. The problem turned out being that the preprocessor was not running, so my changes to Sass files weren’t being applied to the compiled CSS files.
It’s not hard to remember to setup a CSS preprocessor to watch your stylesheets, but it’s just another thing that has to be done and another thing I might forget when I get into work in the morning. Being able to open my text editor and start coding without having to think about it is a very valuable thing.
Conclusion
While CSS preprocessors provide a lot of extra features on top of CSS, those features aren’t necessary if you write your code using the OOCSS approach.
What do you think? Are CSS preprocessors useful even if you use an OOCSS approach?
