2012 February 27 Too LESS? Should You Be Using Sass?

Previously I had updated this article to say that this commit looked like it gives you real variable properties in LESS. I was wrong! So even in LESS v1.3 you are still screwed for doing metaprogramming and working with a real CSS preprocessor. That may change for LESS v1.4 and if you want to help make that happen. I suggst you put your weight behind this github pull request.

First, a little bit of background. A while back ago I took a great deal of my personal time to try out Twitter's Bootstrap project for a Rails application of mine. This meant that I was willing to throw away some of the work I had done in Sass and rewrite it using LESS. No problem I thought, at first glance LESS and Sass look almost identical in functionality. So after some weeks of improving the toolchain for LESS with Ruby and then Rails, I set out to do just that – and what a miserable failure it was. My goal is to share my experiences to anyone considering using LESS and why it might be wrong for your Rails project.

Why Should My Opinion Matter?

For staters, I am the author of less-rails, the gem that allows you to effectively use LESS in the Rails asset pipeline. This gem made other gems of mine like less-rails-bootstrap possible. So now full LESS frameworks such as Twitter's Bootstrap could be leverage natively within the Rails ecosystem. Both of these gems greatly reduced the barrier to using LESS for the average Rails developer and I wrote them for one simple reason. I wanted to make sure LESS was as close to par with Sass in the Rails asset pipeline as possible. So before I rewrote one single line of Sass to LESS, it was going to have a fair shake. This was no small feat! Especially considering that LESS is the only JavaScript based CSS language to be extended with Rails' asset helpers like asset-data-url() . Meaning you can hook into assets from any other place in the pipeline directly from LESS, just as you would with Sass.

Other qualifications? Well I fancy myself a CSS nut and put my skills slightly above average. Most know me as an ActiveRecord or database nerd. But I am just as comfortable doing client side JavaScript and design implementation, especially using HTML5 and CSS3. Very few people know of my design background nor that I have been writing proper presentation layer CSS for over 14 years. Here in the past few years, I have learned to leverage both Sass and the Compass framework like a pro, even for this blog. Here lately, in the project I intended to move to LESS, my Sass usage has become quite impressive. I have extended Sass' color objects to allow HSV from RGB conversions for presentation code parity with similar iOS CoreGraphics drawing code in my native iPhone applications. I have even learned to write Sass mixins using custom functions and tricks I picked up while reading the Compass source. All this placed the bar pretty high for me on how LESS could take the place of Sass in my little experiment.

What Went Wrong?

So my bar was pretty high. I set out to not only rewrite my current Sass to LESS, but I fully expected to duplicate much of the things I learned to love about the Compass framework in LESS as well. And like a good open-source citizen, I even prepared a new project that I dubed protractor on github to share all my work. So what went wrong? Plenty! Every day, mixin by mixin, line by line, I felt MORE pain. LESS was fighting me and it was winning.

Some of the bugs I encountered were fixed, like parsing errors for CSS3 keyframes. Others had horrible workarounds that used more code while at the same time lowering legibility. Finally, I came across the one issue on the hundreds of those that exists on LESS' github page that stopped me cold. It was titled variable property and after learning about it, I decided to stop using LESS for my Rails projects. What are variable properties anyway. Let me show you a common pattern both I and Compass use in a basic contrived example. You may also want to read my comments in that github issue link too. Imagine I have some global colors that I want to mixin to other classes based on a dynamic property. So given this SCSS below:

$ myWhite : rgb ( 240 , 240 , 240 ); $ myGray : rgb ( 140 , 140 , 140 ); $ myBlack : rgb ( 30 , 30 , 30 ); @mixin myColorClasses ( $ property ) { & .white { #{$property } : $ myWhite ; } & .gray { #{$property } : $ myGray ; } & .black { #{$property } : $ myBlack ; } } .box { @include myColorClasses(background-color); }

It would output something like the following. Notice how I use the variable string background-color and generate dynamic properties?

.box.white { background-color : #f0f0f0 ; } .box.gray { background-color : #8c8c8c ; } .box.black { background-color : #1e1e1e ; }

Astute observers may point out that you can achieve the same with sub classes and be more efficient in the generated CSS too. You would be correct. I did say this was a contrived example. The point is that LESS is not a CSS preprocessor and without the ability to dynamically define property values you will be limited in the ways your LESS based CSS framework can compete with frameworks like Compass. Simply put, LESS will never stack up to Sass.

In All Fairness

I have mad respect for Alexis Sellier (@cloudhead). By far his skills and open source contributions well outrank my own. As software developers we need to recognize that there are no absolutes and as such, there is no one tool that is right. You have to weight a ton of other factors and choose the tools that are right for you. I firmly believe that as Ruby and or Rails developers that you should choose to learn Sass and Compass vs. LESS and I am basing my opinion heavily on three criteria.

First is that from a Ruby perspective, Sass will always be more easy to extend and hook into. Second, that LESS lacks a critical feature that I require to author CSS. Lastly, that LESS is not a CSS preprocessors by design and I believe they are the way forward to a better future via the CSSWG. This is what Sass does very very well. I want to treat CSS as a language and use features like loops, lists and custom functions.

Your mileage may vary and please make your own decisions. I would be more than happy to followup with any questions on this topic too, so please ask away in the comments below. Lastly, here are a few other articles that talk about LESS and Sass.