text post 5/9/2012

Battle of the CSS Preprocessors

I love front end dev with a crazy passion, and I spend a lot of time thinking about and using CSS preprocessors. I’ve even been writing one myself just to better understand the implementation (and to teach myself about compilers - I’ve never taken a CS class in my life). I’ve written a large and extensive framework using sass that’s something of a mix between compass and twitter bootstrap. There are thousands of lines of pure sass, and the logic is so complex that I’ve even had a little trouble porting it out to javascript.

Needless to say, I’m very opinionated about css preprocessors, and whenever I see someone doing front end dev and not using one, it makes me cringe. The time they save you is so absurdly much more than the time it will take you to learn how to use their common-sense rules that I would seriously doubt the skills of anyone who calls themselves a front end dev and doesn’t use one. But with a number of preprocessors out there, I see a lot of confusion over which one is the ‘best’, especially for those just starting to learn. In this article, I’ll go over each of the major preprocessors in gritty detail, trying to be balanced in the pros and cons so that you can choose for yourself.

Less

Less is probably the most popular of them, partly because of it’s use in Twitter Bootstrap and partly because it’s docs are the best. Less is also by far the most simple of the preprocessors. It supports nesting, variables, basic mathematical operations, color functions, @import, and basic type functions. The feature set here, perhaps aside from basic type functions, is considered to be the base feature set for a css preprocessor. All of these features are enormously useful, and nesting, mixins, and variables quickly become essential once you are used to working with them.

Because of it’s simplicity and similarity to regular css, making a transition from regular css to less is probably quickest, which is another reason for it’s higher popularity. There are a number of gui apps that will watch and compile your less files for you, and files can be converted on page load with javascript. Less is written in javascript, which is familiar with many web devs (although the advanced structures required to implement a compiler may appear alien to anyone but a serious programmer).

Awesome thing you can do with less

This example demonstrates many of the basic great features of css preprocessors, including variables, mixins, functions, and the parent selector.

Sass

Sass is also very popular, especially since it’s now the default for stylesheets in Ruby on Rails. Sass has all the features that less has, but also includes a large amount of more advanced functionality. There are two dialects of sass available - sass and scss. With scss, parens and semicolons are required as with vanilla css, where in sass, there are no parens or semicolons allowed and the nesting is dictated with whitespace. For someone who writes a lot of css, a whitespace-dependent syntax begins to make a lot of sense, as we almost always indent our css anyway, and this can be a very significant time saver.

Sass includes control directives, which gives it an immense amount of power over less. If/else statements, foreach loops, array lists, and type detection are fair game to use within sass, allowing one to write very flexible mixins. It also includes @extends which allow you to build on a previously defined css rule, and a protocol for extending sass to add your own custom functions. Sass also allows keyword arguments (kwargs) in their mixins, which allows you to make your code more clear and/or switch around the order of arguments. Finally, sass’s color functions are more varied and robust, allowing you to perform nearly magic with colors and color formats. However, sass’s documentation is much less pretty and clear than less’, and finding the docs for the more advanced sass functionality is a bit more difficult and less accessible.

It’s also written in Ruby, which makes it ever so slightly slower than javascript running on v8, less compatible with javascript applications, and easier to use with ruby apps. Sass does however implement caching, which can make it a lot faster during development if you are writing very modular code, as it will only recompile files that were changed. Sass is also very actively developed by a group of intelligent and experienced developer, is constantly coming out with bug fixes, and are often the first to come out with improvements, where I haven’t seen as many major jumps in less (but the recent commit log is looking good).

It’s certainly worth mentioning that sass can be used with a framework called compass, which provides shortcuts for things you often do with sass such as gradients, sprites, and vendor prefixing. There is a large community around both sass and compass which makes it easy to get support if you are just starting out.

Awesome thing you can do with sass

This example takes advantage of sass’s if/else statements and the more terse ternary form to set the text color to light or dark based on the background.

Stylus

Stylus is way ahead as far as features and power, but is also the least popular. It’s hard to think of a feature that stylus does not have. With stylus, you can write your css however you want and mix and match between bracket/semicolon syntax or indentation (with very few exceptions). It also takes terse syntax to the next level by not even requiring a colon between your css properties and values, and by allowing you to include a mixin just like you’re writing a normal css prop/val pair (using the arguments variable).

Stylus also supports all the features that less and sass support with a bunch more on top. You can get properties from parents and pull them into children and/or mixins - if the property isn’t found, it will bubble up until it finds a match. Stylus also has an introspective api, where a css block can tell if it’s at root level or not and change its output based on this. It also supports rest parameters (taking multiple arguments in as an array), can convert images to base64, automatically vendor prefixes @keyframes, and allows you to pass a css literal block wherever you want.

Stylus’ error reporting also stands out - it shows very clearly where in the code you went wrong , surrounded by 3 or 4 lines on either side for context, and an explicit reason. It’s written in javascript and was written specifically for node, which makes including it in node very easy. There is a ruby port though if you want to use it in ruby apps (works with rails and sprockets as well).

Awesome thing you can do with stylus

This example uses the killer feature of being able to trace back up through parents to find out if a property has been defined and if so, pull the value.

Overall

Each of the preprocessors have their advantages and disadvantages. Less is easier to pick up and more similar to css. Sass is a solid rails standard and a very safe and secure middle road that comes with a delightful boost in power. And stylus has every advanced feature you could dream for, as well as a very flexible syntax.

Purely in my opinion, if someone new to preprocessors were to ask me where to start, I would probably recommend sass. It’s a solid starting option and includes advanced features and whitespace significant syntax that you can graduate to if you want. It’s not as basic and limiting as less, but it’s not as advanced and forgiving as stylus. If you have experience with programming or have been using preprocessors for a while already, I would recommend thinking about migrating to stylus for the sole reason that you can make the most magic happen there. It includes everything sass has, has some killer advanced features that no other preprocessor has implemented, and the fact that it’s written in javascript makes it more flexible (porting from js to ruby isn’t too painful, but the other way is).

I’d be more than happy to hear anyone else’s opinions and/or experience here too - join in the discussion on Hacker News!

– also want to give a special thanks to @snugug for his fantastic insight on this topic : )