Twitter Bootstrap, Less, and Sass: Understanding Your Options for Rails 3.1

This entry is part 1 of 3 in the series Twitter Bootstrap and Rails

Twitter Bootstrap and Rails

By now, we’ve all seen Twitter Bootstrap – it’s a great CSS and Javascript library open sourced by Twitter that makes it easy to produce a very polished looking site, with fantastic support for layout, navigation, typography, and much more. Twitter Bootstrap is based on Less.js, the popular dynamic CSS scripting language written by Alexis Sellier or @cloudhead. Less.js, like Node.js, is implemented completely with Javascript. While Less is based on Javascript and not Ruby, some great work has been done just in the last couple of months to make it easy to set up Twitter Bootstrap in your Rails 3.1 app using a variety of different approaches.

Twitter Bootstrap is a great way to
quickly build a very polished web site.

Today I’m going to review the basics of Twitter Bootstrap, and then take a close look at the following gems and libraries: less-rails-bootstrap, sass-twitter-bootstrap, bootstrap-sass and bootstrap-rails. With all of these different options available, it’s hard to know exactly how to get started using Twitter Bootstrap with Rails. Before you dive in and start building the next killer Twitter Bootstrap Rails 3.1 app, be sure to understand how these different gems work under the hood so you can decide which one is right for you and your app.

Twitter Bootstrap basics

On the surface, Twitter Bootstrap is simply a single CSS file, bootstrap.css, that provides all of the style and layout support, along with a few Javascript files that implement various dynamic features. This means the fastest and simplest way to get started using it is just to copy bootstrap.css into your Rails 3.1 app/assets/stylesheets folder like this:

$ git clone https://github.com/twitter/bootstrap.git
$ cp bootstrap/bootstrap.css path/to/app/assets/stylesheets/.

…and you’re off to the races! Use their online demo page as a guide to get started; you can even use “Inspect Element” or “View Source” right on that page to get a sense of what styles they’re using for each feature.

However, as I mentioned above, Twitter Bootstrap is based on the Less.js framework, and the bootstrap.css file is a actually a compiled version of the Less code contained in a series of “.less” code files:

Twitter Bootstrap files

Looking in the Twitter Bootstrap github repo, the Less code files are contained in the lib folder, while the compiled bootstrap.css file is right in the root folder.

If you’re not familiar with Less, it’s very similar to Sass: it provides an enhanced, more powerful language for authoring CSS style code. As with Sass, you can use variables, mixins, nesting, etc. Think of Less as Sass implemented with Javascript instead of Ruby. If you’re interested in learning more about Less take a look at lesscss.org; there’s also a great article out there by Jeremy Hixon, An Introduction To LESS, And Comparison To Sass, that compares the two languages.

Therefore, as explained on the Twitter Bootstrap introduction page, the best way to use Twitter Bootstrap in a Rails site is to use the Less source code written by the Twitter team directly, and not just the compiled CSS output. This allows you take advantage or override the styles provided by Twitter Bootstrap in a very straightforward way. But since Less isn’t supported by the Rails 3.1 asset pipeline, this is a bit of a problem…

Less-rails-bootstrap

Fortunately, Ken Collins did some great work during the past few months to solve this problem; he wrote a new gem called less-rails-bootstrap that adds support for Less into the Rails 3.1 asset pipeline. You can read his blog post or check out his Github readme page for the details. Another gem called twitter-bootstrap-rails by Seyhun Akyürek uses the same approach, although at first glance twitter-bootstrap-rails doesn’t appear to have any tests in it, while Ken’s less-rails-bootstrap does have an effective MiniTest::Spec test suite.

I’ll repeat the setup steps from Ken’s blog post here; first just add less-rails-bootstrap (or twitter-bootstrap-rails) to your Gemfile in the :assets group:

group :assets do
  gem 'less-rails-bootstrap'
end

And install it using “bundle install.” Then all you need to do is require the Twitter CSS code from your app/assets/stylesheets/application.css file like this:

/*
 *= require twitter/bootstrap
*/

As Ken explains, now you’re free to override and manipulate the Twitter Bootstrap Less code directly; for example if you add this code to a new file with a .css.less extension:

@import "twitter/bootstrap";

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

… you now have a cross-browser compatible CSS style that will apply a rounded border with a radius of 4 pixels. But how does this actually work? Let’s take a closer look:

What Gem does what?

In true Rails fashion, it turns out there’s a lot of “magic” going on here behind the scenes. Before using this approach in your application, it’s important to understand which gems are involved and what all of these gems are actually doing for you. Taking it from the top and diving down, here’s how less-rails-bootstrap works:

  • less-rails-bootstrap: Ken’s gem actually includes the Twitter Bootstrap Less code files (in the vendor/assets folder) and provides a Rails engine to make them accessible to your app. More on this in a minute…
  • less-rails: Ken wrote also wrote this gem, based on an earlier version by Karst Hammer, that helps integrate Less with the Rails 3.1 asset pipeline, providing extensions that Rails developers would expect. See Ken’s clarification on this in the comments.
  • less.rb: This gem, written by Charles Lowell, is a thin wrapper around the Less language compiler, allowing your Rails app to call it.
  • therubyracer: Also written by Charles Lowell, this gem provides Ruby programs, in this case your Rails 3.1 app, the ability to call the V8 Javascript engine.
  • libv8: This gem makes it easy to install or compile from source the actual V8 Javascript library, which itself is implemented mostly in C.

With so much code involved, you might ask: Will less-rails-bootstrap slow my application to a crawl? The good news here is that you only need the Javascript V8 engine and all of the other code above it to compile the Less code files into CSS. That is, you’ll only need all of this for development purposes while you’re writing or modifying the CSS styles. Before you deploy to production you’ll precompile your .css.less asset files, the same way you already do with your other CSS or Javascript files – and none of these gems will actually be used on your production web server.

Another important piece of magic that Ken has implemented is the way he packaged up Twitter’s Less code file using a Rails engine. Here’s how that works:

less-rails-bootstrap gem

If you’re not familiar with Rails engines, take a few minutes to watch Ryan Bates explain how they’re implemented in Rails 3.1. Less-rails-bootstrap implements the simplest kind of Rails engine, providing your Rails 3.1 app access to the Twitter code as additional, static asset files. When an HTTP request comes in from the user – in this case you, since you only use this code during development – it’s forwarded on by Rails to the engine in the less-rails-bootstrap gem. In practice, you don’t really need to worry about how this works, but it is good to know where the Twitter Less code files are located, in case you need to find a specific style definition or search for something else:

$ cd `bundle show less-rails-bootstrap`
$ find vendor
vendor
vendor/assets
vendor/assets/javascripts
vendor/assets/javascripts/twitter
vendor/assets/javascripts/twitter/bootstrap
vendor/assets/javascripts/twitter/bootstrap/alerts.js
vendor/assets/javascripts/twitter/bootstrap/buttons.js
vendor/assets/javascripts/twitter/bootstrap/dropdown.js
vendor/assets/javascripts/twitter/bootstrap/modal.js
vendor/assets/javascripts/twitter/bootstrap/popover.js
vendor/assets/javascripts/twitter/bootstrap/scrollspy.js
vendor/assets/javascripts/twitter/bootstrap/tabs.js
vendor/assets/javascripts/twitter/bootstrap/twipsy.js
vendor/assets/javascripts/twitter/bootstrap.js
vendor/assets/stylesheets
vendor/assets/stylesheets/twitter
vendor/assets/stylesheets/twitter/bootstrap.css.less
vendor/frameworks
vendor/frameworks/twitter
vendor/frameworks/twitter/bootstrap
vendor/frameworks/twitter/bootstrap/bootstrap.less
vendor/frameworks/twitter/bootstrap/forms.less
vendor/frameworks/twitter/bootstrap/mixins.less
vendor/frameworks/twitter/bootstrap/patterns.less
vendor/frameworks/twitter/bootstrap/reset.less
vendor/frameworks/twitter/bootstrap/scaffolding.less
vendor/frameworks/twitter/bootstrap/tables.less
vendor/frameworks/twitter/bootstrap/type.less
vendor/frameworks/twitter/bootstrap/variables.less
vendor/frameworks/twitter/bootstrap.less

Sass-twitter-bootstrap

While Ken’s done a great job with less-rails-bootstrap, you may prefer to use Sass instead of Less, because it’s already supported by Rails 3.1 out of the box, or because your application already contains a large amount of Sass code, or possibly just because you’re more familiar with it. At first glance, this seems to be a serious problem for Twitter Bootstrap: it’s not appropriate for a large portion of the Rails community that prefers Sass, since it was implemented with the Javascript-centric Less.js technology.

Don’t worry – some other great developers (John Long, Jeremy Hinegardner and others) ran into this dilemma already and came up with a solution: they translated Twitter Bootstrap’s Less code into Sass, and released that as a separate library on Github, called Sass-twitter-bootstrap.

Sass-twitter-bootstrap is not a gem, but instead is just a github repo containing Twitter’s translated code. To use it in your Rails 3.1 app, just clone the repo and copy the bootstrap css file into your app, like this:

$ git clone https://github.com/jlong/sass-twitter-bootstrap.git
$ cp sass-twitter-bootstrap/bootstrap.css path/to/app/assets/stylesheets/.

Of course, this isn’t really any different than copying the bootstrap.css file directly from the Twitter Bootstrap repo; instead what you should do is copy the Sass source files right into your application like this:

$ rm path/to/app/assets/stylesheets/bootstrap.css
$ cp -r sass-twitter-bootstrap/lib path/to/app/assets/stylesheets/twitter

And now since the Rails 3.1 asset pipeline supports Sass out of the box, we’re good to go… almost! If you run your app now, you’ll see an error:

ActionView::Template::Error (Undefined variable: "$baseline".
  (in /path/to/app/assets/stylesheets/twitter/forms.scss))

Thanks to Brent Collier, there’s a simple solution for this problem: the code in application.css by default uses “require_tree” to include all of the code under app/assets/stylesheets:

/*
 * This is a manifest file that'll automatically include all the stylesheets available in this directory
 * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
 * the top of the compiled file, but it's generally better to create a new file per style scope.
 *= require_self
 *= require_tree .
*/

As Brent explains, the problem with this is that Twitter Bootstrap’s Less code (and the translated Sass version) was designed to be included once using the bootstrap.scss file, which in turns includes all of the other files. Brent’s solution works perfectly: just remove “require_tree” and require bootstrap.scss directly:

/*
 * This is a manifest file that'll automatically include all the stylesheets available in this directory
 * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
 * the top of the compiled file, but it's generally better to create a new file per style scope.
 *= require_self
 *= require twitter/bootstrap
*/

Conceptually, here’s what this setup looks like:

Copying sass files

The benefit here is that now you have Sass code implementing Twitter Bootstrap directly inside your Rails 3.1 app! This means you can go ahead and use, override or modify the Sass to your heart’s content.

The obvious drawback here is the manual copy process involved. You’ll need to copy the Sass code files once into your Rails app to get started, but then you’ll have to repeat the copy each time Twitter releases a newer, better version of Twitter Bootstrap. While this won’t happen every day, why set yourself up for an ongoing maintenance problem?

Another drawback is that you’re using a second-hand, translated version of Twitter’s code, and you’ll have to trust the people who maintain sass-twitter-bootstrap to accurately translate the Less into Sass.

Bootstrap-sass and bootstrap-rails

Like everything in the Rails world, there are always other good solutions out there you can take a look at, in this case the bootstrap-sass gem by Thomas McDonald and the bootstrap-rails gem by AnjlLab. Both of these gems combine the Sass translation approach with a Rails engine to avoid the manual copy maintenance headache.

Using bootstrap-sass (or bootstrap-rails) is a simple as adding it to your Gemfile:

group :assets do
  gem 'bootstrap-sass'
end

Run “bundle install” and then add a require statement to app/assets/stylesheets/application.css:

/*
 *= require bootstrap
*/

Similar to less-rails-bootstrap, this works by having Rails 3.1 load the Sass code from a Rails engine inside the gem:

Bootstrap sass and rails

So there’s no need to download and copy either the Twitter Bootstrap Less code, or its translated Sass version. As new versions of Twitter Bootstrap are released, presumably Thomas McDonald will re-translate the Less code into Sass, and re-release his gem. Then you’ll be able to just run “bundle update” to get the new Twitter code into your application!

Other options

Amazingly, there are even more options out there for integrating Rails 3.1 and Twitter Bootstrap that I don’t have time to cover today:

  • compass-twitter-bootstrap is similar to bootstrap-sass and bootstrap-rails, using a Rails engine to provide a translated version of the Twitter Bootstrap code, but is geared instead to the Compass CSS framework.
  • twitter_bootstrap_form_for implements a custom Form Builder object, the object yielded by form_for in your view, designed specifically for Twitter Bootstrap.
  • css-bootstrap-rails is similar to bootstrap-sass and bootstrap-rails, but uses a Rails engine to include only bootstrap.css without any Less or Sass files.

Six of one, half dozen of the other

All of these approaches will work equally well:

  • Using the original Less code via a Rails engine (less-rails-bootstrap or twitter-bootstrap-rails)
  • Copying in translated Sass code directly into your application (sass-twitter-bootstrap), or
  • Using a translated Sass version via a Rails engine (bootstrap-sass or bootstrap-rails).

Less and Sass are very similar, and using one language or the other is really a matter of personal preference. Similarly, using a Rails engine is a convenient way to include the Twitter Bootstrap code in your Rails 3.1 app and to manage upgrades smoothly. However, using a Rails engine adds some additional “magic” to your app and can be somewhat confusing when you need to find, inspect or search against the Sass code. There’s a simple elegance to the approach of just copying the Sass code right into your app, and you may not often need to update to a newer version of Twitter Bootstrap.

Which approach to take is up to you!

And if you enjoyed reading this post, you’ll love Learnable; the place to learn fresh skills and techniques from the masters. Members get instant access to all of SitePoint’s ebooks and interactive online courses, like Jump Start Rails.

Comments on this article are closed. Have a question about Ruby on Rails? Why not ask it on our forums?

Twitter Bootstrap and Rails

Too good to be true! Twitter Bootstrap meets Formtastic and Tabulous >>

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://www.decioferreira.com Décio Ferreira

    Great article Pat. A bit of shameless self promotion, but could I just suggest one more option, my bootstrap-generators gem that provides Twitter Bootstrap generators for Rails 3.1.

    The gem is usable but still under development, so feedback or contributions are very welcome.

    • http://patshaughnessy.net Pat Shaughnessy

      Thanks Décio! I’ll definitely check out your gem; using generators is one approach I hadn’t thought of before…

  • http://metaskills.net/ Ken Collins

    Pat, another great article! Some feedback:

    First, I have never used RSpec, both the less-rails and less-raills-bootstrap projects use MiniTest::Spec. I tend to use bare bones testing frameworks for my projects so I can stay away from complex test systems for the gems I author. I like that MiniTest is the TU replacement and part of ruby-core.

    Also, technically Tilt, when used with Charles’ less.rb gem, is enough to render css.less templates in the asset pipeline. I made the less-rails gem to solve two critical problems (a) a standard way to augment less.rb’s paths to when used with the asset pipeline, critical for gems like less-rails-bootstrap to hook into and (b) provide extensions to less.rb that rails developers would expect, like the asset url helpers. My favorite of which is the asset-data-url for base64 encoded images.

    Another key reason that I made less-rails-bootstrap was to solve the lack of name-spacing I witnessed in other packages including the bootstrap file. I predict that as the asset pipeline gains more adoption, people will learn that there assets need to be namespaced (via directories) just like we are used to our gems and models. So you are free to happenstantially make your own variables.less file in your assets path and never worry about it conflicting with twitter/bootstrap/variables.less. No other gems that I saw are thinking about this potential problem we will face and eventually gem authors will start to understand the importance of namespacing their assets. Because of this the recent less-rails-bootstrap tries to follow a convention I found in Sass/Compass where the path to the raw source files are in a vendor/frameworks directory, which I use less-rails to make sure is in the renderable paths for less.

    Again, great article!

    • http://patshaughnessy.net Pat Shaughnessy

      Thanks for your kind comments, Ken! And thanks so much for the corrections. Yea it’s funny the MiniTest::Spec code resembles RSpec at first glance, actually… I’ll have to try MiniTest myself soon. And sorry to get the purpose of the less.rb gem wrong; thanks for the thorough clarification. I’ve updated the article text above for both mistakes.

      You make a good point about namespacing – that sounds like a really great idea.

      Maybe what I’ll do is write a follow up article someday soon about more of the details of how Less and the Rails asset pipeline work together. I was covering so much ground in this article I really didn’t have time to get into the real details. …or maybe I should let you write that one :)

      Keep up the great work on less-rails-bootstrap!

  • oz

    “Less.js, like Node.js, is implemented completely with Javascript.” Hm nope. Node.js is a good deal of Javascript, but it wouldn’t exist without all the C++ around it. ;)

    Nonetheless, thanks for a great article.

  • http://billchristian.posterous.com Bill Christian

    Which option is best for overriding the Bootstrap variables? I get a little lost on how I can change the base link color (in less or sass versions) without editing the source files.

    • http://patshaughnessy.net Pat Shaughnessy

      Hi Bill, If you’re using Less and have the less-rails-bootstrap gem installed, then just create an custom_variables.css.less file anywhere under app/assets/stylesheets and add this Less code to it, for example:

      @import “twitter/bootstrap”;
      @linkColor: #0F0;

      If you’re using Sass, then you don’t need any gem installed since Rails 3.1 supports it by default. So you just need to create custom_variables.css.scss file instead, and then use this Sass code inside it:

      $linkColor: #F00;

      But for Sass it looks like you’ll have to modify the bootstrap.css.scss file – either the one you copied from sass-twitter-bootstrap or else the one inside of bootstrap-sass, for example – and import your new custom_variables.css.scss file like this:

      @import “bootstrap/variables”;
      @import “custom_variables”;
      @import “bootstrap/mixins”;

      This last part seems very ugly to me; I’ll look into it some more and write here again if I find a cleaner way to override Sass variables.

      • http://billchristian.posterous.com Bill Christian

        So if I understand correctly, I can override the *existing* LESS variables defined in the original sources by using the import and the new LESS statement. Do I need to modify the require statement in the application.css to specify a cascading order? Also, should i just import the twitter/bootstrap/variables file or do I need to bring in everything in my override file?

        Thanks for your help. If you have a gist or github showing an example, I’ll stop with the questions.

      • Thomas McDonald

        Indeed it is, and the update to bootstrap-sass I’ve just pushed means that if you define the variables you want to change before you @import “bootstrap” then SASS will not overwrite your previously defined variables with the bootstrap defaults.

        • http://patshaughnessy.net Pat Shaughnessy

          Cool! Thanks for letting us know, Thomas. I’ll get and try out your changes very soon…

        • Larry

          Is there a way to override the mixins defined by bootstrap when using sass-bootstrap?

  • http://patshaughnessy.net Pat Shaughnessy

    Questions are no problem at all! I’m happy to try to help. And sorry for the slow reply – this is actually a complicated issue.

    So after some more research, I now think the best way to override Twitter Bootstrap variables is to:

    1. Remove application.css and instead use application.css.less or application.css.scss, and:
    2. Import (not require) each of the TB files individually, including your override values after including the TB variables file.

    Application.css.less example (using less-rails-bootstrap): https://gist.github.com/1389826

    Application.css.scss example (using bootstrap-sass for example): https://gist.github.com/1389831

    Both Less and Sass seem to have the same issue, and work equally well.

    Notes:

    - If you instead used @import on the entire TB tree, like I show above in the article, then all the TB css code might be included more than once in your generated css file!

    - In either case you should not use require_tree, but just require_self.

    See: http://stackoverflow.com/questions/6420460/in-rails-3-1-is-it-really-impossible-to-avoid-including-duplicate-copies-of-sty and http://railscasts.com/episodes/268-sass-basics for more details on this.

    Sorry for the long comment – I should have covered this in the article :)

  • http://billchristian.posterous.com Bill Christian

    Really appreciate the help!

  • ankur

    This is a great article, I was also confused at the large variety of gems, good work straightening this out.

  • http://douglastarr.com Douglas Tarr

    This is a great overview, you’ve saved me a bunch of time. Thanks Pat!

  • http://keynotopia.com Caroline

    Thanks Pat! A very helpful and comprehensive overview :)

    Just thought I’d share – Keynotopia has created free Twitter Bootstrap templates that you can download here: http://keynotopia.com/bootstrap/ Great for getting your ideas out in wireframes/mock-ups before getting into the CSS/Javascript.

    We’re hoping they will be helpful to the design community! Feel free to contact me with questions or feedback. I would be interested in hearing your thoughts on them.

  • http://geniustrade.com Carlier

    Please have a look on my project, I’ve fork the seyhunak project to use directly the official source of bootstrap.

    So each time twitter bootstrap is updated you can get it directly in your rails project!

    https://github.com/keysen/twitter-bootstrap-rails

  • http://www.ibeck.com Chris Beck

    I always worry too much about choosing the optimal solution. Fortunately, there are people like you who cater to anal retentives like me by explaining all the choices. Thanks a million.

  • http://rockingchairllc.com veesh

    Hey i tried using Sass-twitter-bootstrap according to the directions here, but the copy command doesn’t seem to include the icon and js files. When i try calling an icon using the tag in code, icons don’t display, understandably. I tried copying the img folder from TwBootsrap into “Twitter” folder under Assets/Stylesheets, but icons still don’t display. Any advice appreciated!!!!

  • berto

    When you’re using the ‘twitter-bootstrap-rails’ gem, if you wanted to replace assets such as icons, where in your project would you place those images. For example, if you want to replace: glyphicons with your own icon sprite.

    I have this in my bootstrap overrides:
    @iconSpritePath: asset-path(‘twitter/bootstrap/glyphicons-halflings.png’);

    but I don’t know where the ‘twitter/bootstrap’ path is. I’m using rails 3.1.

    Thank you. Great article.

  • Rafael

    Hey thanks for the overview, very useful!.

  • Stephen

    Thanks God you wrote this! I’ve been struggling all morning with how to use bootstrap in Rails and this article is a God send!

  • Mark

    Can you offer any help as to what to do with a bootstrap theme that does not use LESS? All the themes from wrapbootstrap.com are listed as “Uses LESS = No”. I downloaded one of the themes and I just can’t get it to work properly. I don’t know if I should be using a gem or what, and where to put all the asset files? Any help would be great.

  • R-on

    Thank you very much for this great article. But the “Less-rails-bootstrap”-way did not work for me – Can anyone verify this?
    (http://stackoverflow.com/questions/15222455/rails-3-2-12-with-less-and-twitter-bootstrap-v8-error)

    Just another hint: Please modify the part “Bootstrap-sass and bootstrap-rails”. According with the documentation of this gem:
    “Import “bootstrap” in your SCSS file of choice to get all of Bootstrap’s styles, mixins and variables! We recommend against using //= require directives, since none of your other stylesheets will be able to use the awesome mixins that Bootstrap has defined.”

    Have a nice day!

  • Cristian

    Thanks a lot! I wish I had found this article at the beginning of my search.

  • https://github.com/scottvrosenthal/twitter-bootswatch-rails Scott

    Here’s a twitter bootstrap rails gem that uses the asset pipeline to make customization simpler by providing easy ways to override the less & javascript defaults.

    https://github.com/scottvrosenthal/twitter-bootswatch-rails

    Bonus, the gem includes import functionality for http://bootswatch.com that can import anyone of the free bootstrap themes into your next rails project.

    Enjoy!