Convert Less to SCSS

Posted May 3, 2010

I haven’t been posting most of the minor RC releases of Haml and Sass to this blog since they only contain bug fixes and usability improvements, which (while important) aren’t very exciting. However, there were fewer bug reports than I anticipated, so I’ve had a little time to work on something extra a couple people have requested: a Less to SCSS converter.

This is being added to sass-convert as part of RC 4, released just now. It is violating the feature freeze, I admit, but since it’s so orthogonal to the rest of the project I don’t think it’ll be a problem. To get it and use it, run:

# Install Sass 3.0.0.rc.4
gem install haml --pre
# Convert all .less files to .scss
sass-convert --from less --to scss --recursive path/to/stylesheets

The conversion is done using Less’s parser, so the less RubyGem should be installed. Presumably it’ll already be there for most people doing the conversion, though.

Incompatibilities

Because of the reasonably substantial differences between Sass and Less, there are some things that can’t be directly translated, and one feature that can’t be translated at all. In the tests I’ve run on open-source Less stylesheets, none of these have presented issues, but it’s good to be aware of them.

First, Less doesn’t distinguish fully between mixins and selector inheritance. In Less, all classes and some other selectors may be used as mixins, alongside more Sass-like mixins. If a class is being used as a mixin, it may also be used directly in the HTML, so it’s not safe to translate it into a Sass mixin. What sass-convert does instead is leave the class in the stylesheet as a class, and use @extend rather than @include to take on the styles of that class. Although @extend and mixins work quite differently, using @extend here doesn’t actually seem to make a difference in practice.

Another issue with Less mixins is that Less allows nested selectors (such as .body .button or .colors > .teal) to be used as a means of “namespacing” mixins. Sass’s @extend doesn’t work that way, so it does away with the namespacing and just extends the base class (so .colors > .teal becomes simply @extend .teal). In practice, this feature doesn’t seem to be widely-used, but sass-convert will print a warning and leave a comment when it encounters it just in case.

Finally, Less has the ability to directly access variables and property values defined in other selectors, which Sass does not support. Whenever such an accessor is used, sass-convert will print a warning and comment it out in the SCSS output. Like namespaced mixins, though, this does not seem to be a widely-used feature.

Beau Smith said May 17, 2010:

Thanks! This script made it very easy to convert from less to sass. Unless it was un-documented, this script strips out all comments. It’d be great to have a flag to not remove comments when converting.

Nathan said May 17, 2010:

The problem with that is that Less’s parser is not capable of preserving comments. Moreover, it’s written using the Treetop parser generator, which makes it impossible to extend without copying the entire thing over. Since I’m not willing to bring in all the Less source code for this, I’m afraid you’re out of luck with respect to comments.

Unless someone wants to hack Less to support them, that is.

Beau Smith said May 19, 2010:

Thanks for the response Nathan. There weren’t too many comments, so it was pretty easy to manually move them over.

Andy said July 13, 2011:

Thanks for your work. I have a problem when using ruby-1.9.2-p180, rails (3.0.7), haml (3.1.2) and sass (3.1.4, 3.1.3) while converting:

https://gist.github.com/1080072

Andy idea what’s going wrong?

Thanks

Andy

Nathan said July 13, 2011:

Andy: it’s possible that Less’s parser is incompatible with Ruby 1.9.2. What version of Less do you have installed?

Juergen said September 01, 2011:

Thanks so much for the post. I was trying to convert Bootstrap http://twitter.github.com/bootstrap/ to scss using your example above, though, running into an error where sass-convert throws an error.

undefined method `build’ for module `Less::StyleSheet::Mixin4’ (NameError)

gem list less (2.0.6) sass (3.1.7) ...

The error does is not thrown if you install an earlier version of less, e.g. 1.2.x

Mike said December 29, 2011:

I had the same error message as Juergen (with less(2.0.8) and sass(3.1.12))

@Juergen: See https://github.com/jlong/sass-twitter-bootstrap

Make your comments snazzy with Textile!