We know that CSS has its limits. We also know about the unavoidable slowness with which the language is being developed and implemented for browsers. CSS preprocessors have been designed to provide a solution to these problems. They allow developers to avoid writing CSS, and to create stylesheets by using a new meta-language; one that is more powerful and expressive than CSS itself and which can be compiled in simple CSS that can be included in web pages.
So, how long have we all been talking about CSS preprocessors for now? Eight years. Not a short amount of time in our world. Sass, the first project to implement the idea was released as long ago as 2007.
Initially, the project was supported principally by Ruby developers — the hipsters of the epoch, if you will. However, with the passing of time it has slowly and inexorably spread its reach to become a widely recognized tool that can be used in virtually all technology stacks. It has now reigned uncontested, unthreatened by any of its competitors, for at least three years.
- Homepage: http://sass-lang.com
- Created at: September 2007
- Github stars: ★ 5.138
- Homepage: http://learnboost.github.com/stylus/
- Created at: December 2010
- Github stars: ★ 5.173
- Homepage: http://lesscss.org
- Created at: February 2010
- Github stars: ★ 11.617
How are they different from each other?
Well, let’s start with the similarities. All three of the languages, albeit with a few qualifications, support:
- Scripting using variables, functions, iterations and conditionals;
- In-line concatenation of secondary files by means of `@import;
- Nesting of CSS selectors;
- Mathematical functions and functions for managing colours and basic types;
Less.js, unlike Sass and Stylus, does not support:
- Hash structures;
- The ability to write code using a syntax with significant-whitespace;
- Selector inheritance using the
@extenddirective, useful for inheriting CSS rules from a selector without creating duplicate code;
In 2014 the Sass and libsass teams reached an agreement to coordinate the release of new additions. A move that quickly led to an almost perfect synchronization of their features: the list of the (few) incompatibilities between the two motors remaining today has been well documented by the Sass Compatibility projected.
As expected, the release of libsass has allowed the language to expand into environments in which a runtime Ruby could not previously be utilized. Today, binding libraries for libsass exist in all of the principal languages, including — obviously — Ruby and Node.js.
Unlike Sass, Less.js and Stylus can carry out the step of precompilation directly on the browser side, without needing to resort to the use of any external tools.
Transpilers and post-processors to the rescue.
Rather than involving the creation of a new metalanguage, the project consists of “augmenting” the results of regular CSS by means of a compilation step.
The most popular examples of this?
- Autoprefixer makes it possible to write CSS code without having to worry about vendor-prefixes. These are added automatically, based on a selection of the population of the browser that it is intended to support, drawing on the latest data available on caniuse.com.
- cssnext, makes it possible to write CSS4 files now, including the advanced behaviours that have already been standardized and those present in the various preprocessors currently available: variables, expressions calc(), semantic media queries, custom selectors, etc. The compilation step reproduces the behaviour described in CSS3 syntax.
The Lean Panda team have had long experience with Sass — in fact we have recently “formalized” our way of operating and structuring Sass projects with the release of BEMO.
Well, the analysis we’ve carried out here hasn’t given us any practical reasons that might motivate us to switch to an alternative preprocessor.
In addition to the general “draw” in terms of the features they provide, I feel that I ought to make one further point in favour the Sass’s team’s approach to the release of new functionality, which is well summarized by the words of Hugo Giraudel:
What I do like with Sass is its conservative approach to CSS. Sass’s design is based on strong principles: much of the design approach comes naturally out of the core teams’ beliefs that a) adding extra features has a complexity cost that needs to be justified by usefulness and, b) it should be easy to reason about what a given block of styles is doing by looking at that block alone.
Also, Sass has a much sharper attention to detail than other preprocessors. As far as I can tell, the core designers care deeply about supporting every corner-case of CSS compatibility and making sure every general behavior is consistent.
Returning to Sass, we have had the opportunity to test the libsass engine on a range of projects that have now been in production for several months, and we haven’t observed its having any particular problems compared to its older brother. We therefore feel inclined to recommend it, and are awaiting a solution that will let us make use of it inside Sprokets, Rails’ asset-pipeline.
The cssnext project is certainly interesting: at least in theory, the idea of being able to write using CSS4 (or its standard) instead of having to invest in alternative metalanguages makes sense, and would offer a way of ensuring that the work put into it doesn’t end up “dead” in the space of a few years. In practice, however, despite its many improvements when compared with CSS3, the concept of scripting — so fundamental to frontend projects of medium complexity — continues to be entirely absent.
As regards the management of the browsers’ vendor prefixes, Autoprefixer has demonstrated itself to be the best solution available; far superior to mixin, in stile, Compass or Bourbon, which require more maintenance over time. We have used Autoprefixer with great success in conjunction with Sass both within Rails applications (using autoprefixer-rails) and on client-side projects (with gulp-autoprefixer). It now forms part of our standard toolchain.