Switching from Ruby Sass to LibSass

By James Steinbach

If you’ve been following the recent major announcements from the Sass community, you may have seen the huge LibSass 3.0 announcement at SassConf 2014.

For some time now, the Sass Ruby gem has been getting more advanced features, while LibSass has been updated less quickly. This means that many people using LibSass to compile their Sass (usually through node-sass in a Grunt/Gulp workflow) have been unable to use cutting edge Sass tools like the ones you keep reading about here on SitePoint.

The big announcement is that Ruby Sass will now wait for feature parity with LibSass, then they’ll be maintained at the same speed as much as possible. LibSass 3.0 is out now and you can integrate it into your task runners with the most recent node-sass version.

What makes LibSass so important, however? The biggest advantage over Ruby Sass is that it’s faster – much faster. If faster complile times sound good to you, here’s a good introduction to installing LibSass.

In this article, I’m going to be really practical: I’m going to share all the “gotchas” I discovered when I tried compiling my mixin library with LibSass. While LibSass 3.0 is close to Ruby Sass 3.4.6, there are several things that don’t work identically. You may not face all of these in your Sass, but if you do run into these little bugs, I hope this list helps you troubleshoot them.

Note: in this article, “Ruby Sass” always refers to 3.4.6 and “LibSass” always refers to 3.0.1, unless otherwise specified.

Don’t test with @if not ...

In Ruby Sass, @if not not index($list, $value) {} was a clever way to ensure that a value was in a list. I’ve been using this condition in my Ruby Sass projects since Hugo suggested it to force the condition to evaluate a true boolean value.

However, in LibSass not does not work, so this method appears to always evaluate to true. In LibSass, you can workaround this problem by using one of the following:

@if index($list, $value) { ... }
@if index($list, $value) != null { ... }
@if index($list, $value) > 0 { ... }

Check this out in this Sassmeister gist.

Watch your math syntax.

Ruby Sass will let you get away with the following:

$map: (value: 1200px);
.container {
    max-width: map-get($map,value)-1;
// Ruby output: 1199px
// LibSass output: 1200px -1

LibSass, however, expects you to put a space before and after the minus symbol:

$map: (value: 1200px);
.container {
    max-width: map-get($map,value) - 1;
.container {
  max-width: 1199px; }

Check this out in this Sassmeister gist.

@error doesn’t work.

In Ruby Sass, @error prints an error to the console and stops the compiler. It also allows you to interpolate variables into a helpful error message.

However, in LibSass, the @error line will simply be printed to the compiled output as though it were a CSS declaration line. Because it’s simply being printed to output, it won’t interpolate variables if they’re inside of quotes. I suppose you could still use the broken @error directive and search your output for ‘@error’. If so, you could workaround the variable interpolation issue with string concatenation:

$error-text: 'error text';
.at-error {
  color: blue;
  @error 'Error: #{$error-text}.'
  @error 'Error: ' + $error-text + '.';
.at-error {
  color: blue;
  @error 'Error: #{$error-text}.';
  @error 'Error: error text.'; }

See this in action on this Sassmeister gist.

(@warn still prints a warning to your ‘console’ and keeps compiling.)

Neat grids work; Susy doesn’t work yet.

Not long ago, I wrote about switching from Neat to Susy for Sass Grids. If you’re using LibSass, however, I’d urge you to hold up on that switch. Susy doesn’t run on LibSass quite yet. However, even though Susy doesn’t work as-is, you can create your own grid system using Su.

Neat, on the other hand, just uses variables for config properties: it’s working fine on LibSass right now. See how Neat works on LibSass in this Sassmeister gist.

selector-*() functions with & aren’t supported.

If you’re one of the rare people who has found a good use case for the new selector- functions in Sass 3.4, those won’t follow you into LibSass. I don’t have a work-around to suggest for that, other than “review your nesting strategy” (which would probably remove a need for selector interpolation entirely).

The @at-root directive doesn’t work.

Ruby Sass allows you to use @at-root to move a nested selector out of its nesting context. LibSass, however, treats @at-root like a selector string and prints it to the stylesheet:

.at-root-test {
  content: 'parent';
  .nest {
    content: 'child';
    @at-root .selector {
      content: "not nested";
.at-root-test {
  content: 'parent'; }
  .at-root-test .nest {
    content: 'child';
    @at-root .selector {
      content: "not nested"; }

Again, the workaround for this is to refactor your nesting. Check this out on this Sassmeister gist.


Maps support is one of the biggest features added to LibSass 3. Common map functions work just the way you’d expect. You can use map-keys(), map-values(), map-has-keys(), map-get(), and map-merge() in LibSass 3.

Maps, as you’ve gathered by now, are largely on par between Libsass 3 and Ruby Sass. Enjoy using them!


Another major addition to LibSass 3 is @extend support. I’m not aware of any differences between Ruby Sass and LibSass on this now, but it’s a substantial enough upgrade that it deserves to be mentioned here.

You can see @extend working in LibSass in this Sassmeister gist.


The speed improvements you’ll get from switching to LibSass are huge. However, there are still a few areas where LibSass features are not on par with features Ruby Sass 3.4+. If your mixin library depends on those specific features, hold off on updating for now.

If you’ve moved to LibSass and found other issues or some other syntax tweaks or workarounds, please share those in the comments!

  • Dillon de Voor

    This might be seen as shameless self-promotion (it is) :P But I made a guide installing LibSass that doesn’t involve editing SassC’ Makefile (since this is bad practice) and also handles initialization of the submodule sass2scss since you will get an error otherwise.

    Nice overview of upgrading gotchas. LibSass’ speed is awesome, hope someday there will be a faster implementation of Autoprefixer as well!

  • Joho

    Compass support would make me switch.

  • James Steinbach

    Here’s a LibSass-friendly version of the Compass mixin library:

    • Joan Riba Minnoye

      Hi James. Do you know how to install this? I can’t figure out. Thank you.

      • James Steinbach

        I don’t, sorry. I’m just getting into Grunt & using libsass to compile; I haven’t added any Sass libraries to it.

      • Rene

        Any luck with installing this?

  • Sander Elias


    I have this functionality I need for an library that uses libSass, but it gives me a headache.
    here is an sample of what the problem is:

    have a close look at colorNames and colrNamesInError.

    the second one is mangled, and unusable, but I still need something like that.

    edit: a update here, there is this as a workaround, and the problem was not map-key apparently. (but the interpolation system)

  • James Steinbach

    Another great resource is Hugo Giraudel’s Sass Compatibility Table:

  • Gregor Albrecht

    Does anyone know if the new Libsass release supports susy now? I’d love to stick with libsass and also use susy!

    • Alexadark

      Hi, the new susy version is compatible with libsass:
      discover that yesterday.
      if you use codekit like me, you will need to install susy manually, as the codekit version is not up to date.
      Also remove breakpoint that is not compatible with libsass, and susy-breakpoint is now build in susy.
      just pass from 7s to 1s, so happy!!!
      enjoy :-)
      I also use bourbon, and the last version is not compatible with libsass, so i install an older version, and everything works fine :-)

  • Sp

    Anyone found a work around for – @at-root property, if you have please let me know.

  • Gregor Albrecht

    Thanks! Just switched back to ruby sass to try out susy and it’s just not the same… Gonna try your approach next!

    • Alexadark

      btw, i try again with codekit and their version of susy and it works, but you have to delete breakpoint as it doesn’t support libsass, and not needed anymore in the last version of susy

  • Joel

    Does anyone know offhand if LibSass will work with Bootstrap? (the Sass port obviously – )

  • Adam Molnar

    If you extend a non existing placeholder class in libsass not even a warning will be output. This can be annoying after refactoring or putting in a small typo.
    E.g. %foo { … } .class { @extend %fooo; } will build with success while Ruby Sass will abort.

  • Ben Mirkhah

    Nice article, for the record Susy2 now works just fine with libsass: 3.2.4-26



Because We Like You
Free Ebooks!

Grab SitePoint's top 10 web dev and design ebooks, completely free!

Get the latest in Front-end, once a week, for free.