Ruby, JavaScript, Sass, iOS. Stinky Cheese & Beer Advocate. Working at CustomInk and loving it!

LESS Is More - Using Twitter's Bootstrap In The Rails 3.1 Asset Pipeline

LESS - The Dynamic Stylesheet language This weekend I decided to experiment with LESS CSS by replacing the existing Sass and Compass code that had been built thus far a small project. Why? Three basic reasons. First, I wanted to see how LESS stacked up. Second, I was intrigued by some of LESS' features, in particular their namespace support. Lastly, I wanted to use Twitter's Bootstrap project as a baseline for my design. Since Rails 3.1 has been out for some time, I was expecting the move to LESS to go considerably smoother than my pre-release attempts with Compass and Sass. I was wrong.

So the tilt gem already supported LESS templates and that means that Sprockets and the asset pipeline rendering technically did too. But there was no official less-rails gem that setup a standard configuration for other gems to hook into. This meant that libraries that distributed the Twitter Bootstrap assets were often hard to use or had inconsistent results. For example, it was not possible to load the Bootstrap's assets in such as way that let you build on top of the LESS mixins they had build. Nor were those assets namespaced in such a way that would allow you to have a modal.less asset as it would have conflicted with Bootstrap's version. So since I apparently have a bunch of free time and I hate building on top of a bad foundation, I set out to learn both Rails::Railtie and Rails::Engine to build the proper tools for LESS and Bootstrap in the Rails 3.1 asset pipeline.

New LESS Gems

I introduce you to both the new less-rails and less-rails-bootstrap gems. Take a look at the source code if you ever wanted to learn how to implement a simple Rails::Railtie or Engine. But assuming you want to use Twitter's Bootstrap, here are a few examples to get you started. First just bundle up to less-rails-bootstrap, it will automatically pull in less-rails and less.rb via their dependencies. BTW, I am going to keep the semantic versioning of the less-rails-bootstrap gem in sync with the major and minor versions of the Bootstrap project.

gem 'less-rails-bootstrap', '~> 1.3.0'

From here, the easiest way to use Bootstrap is to require it in your application.css file. Doing so will compile the complete LESS libraries files for Bootstrap. Note how we namespace the files using a simple directory structure.

/*
 *= require twitter/bootstrap
*/

#foo {
  /* Your styles... */
}

Alternatively, in a file with the .css.less extension, you can import the entire Bootstrap LESS framework. This will allow you to use Bootstrap's variables and mixins in your CSS that follows. Remember, unlike other CSS frameworks, requiring or importing Bootstrap will include all the CSS for building a bootstrapped website. If you only want variables or mixins, you will have to import those discreet files, see next section.

@import "twitter/bootstrap";

#foo {
  .border-radius(4px);
}

Maybe all you want to use are the variables and mixins that come with Twitter Bootstrap. No problem, just import them individually from you own .css.less file. In this case only the #foo selector is output.

@import "twitter/bootstrap/variables";
@import "twitter/bootstrap/mixins";

.myButton(@radius: 5px) {
  .border-radius(@radius);
}

#foo {
  .myButton(10px);
}

Using the Bootstrap JavaScript files is just as easy. Again, you can include all them with a single directive from your application.js file. Optionally, you can require only the files you need like require twitter/bootstrap/modal.

//= require twitter/bootstrap

$(document).ready(function(){
  //...
});

The less-rails project has already started getting some good feedback. Soon we hope to implement all the features that you may have used in the sass-rails project, like asset pipeline helpers. One last thing, I wanted to say thanks to Nicolas Mérouze for opening up the old less-rails gem space on rubygems.org for the new gem!

Resources