Twitter Bootstrap, Less, and Sass: Understanding Your Options for Rails 3.1
- Twitter Bootstrap, Less, and Sass: Understanding Your Options for Rails 3.1
- Too good to be true! Twitter Bootstrap meets Formtastic and Tabulous
- How to Customize Twitter Bootstrap’s Design in a Rails app
![]() |
| Twitter Bootstrap is a great way to quickly build a very polished web site. |
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.
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:
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:
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:
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:
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:
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!






The gem is usable but still under development, so feedback or contributions are very welcome.
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!
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!
Nonetheless, thanks for a great article.
@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.
Thanks for your help. If you have a gist or github showing an example, I'll stop with the questions.
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 :)
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.
So each time twitter bootstrap is updated you can get it directly in your rails project!
https://github.com/keysen/twitter-bootstrap-rails
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.
(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!
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!