Twitter Bootstrap and Rails

by Daniel Kehoe

Last updated 5 December 2012

Twitter Bootstrap and Rails. Shows how to set up a Rails 3.2 application to use Twitter Bootstrap as a CSS/JavaScript/HTML5 front-end framework, providing an HTML5 application layout and CSS styling for Rails alerts and notices.

You can use Twitter Bootstrap to quickly add attractive CSS styling to your application. Twitter Bootstrap and other CSS “front-end” frameworks (such as Zurb Foundation) are toolkits that provide the kind of structure and convention that have made Rails popular for server-side (“back-end”) development. Twitter Bootstrap is the most popular of the various CSS front-end frameworks.

What’s Here

This is a guide for developers using the example apps from the RailsApps repository. Others may find it helpful as well. We recommend using the Rails Composer tool (“like the ‘rails new’ command on steroids”) to install Twitter Bootstrap and set up your default application layout. Rails Composer will offer to install Twitter Bootstrap or other CSS front-end frameworks and set up your default application layout accordingly. An example app and Rails tutorial for Devise with CanCan and Twitter Bootstrap gives an example of a complete working application offering user authentication and administrative authorization combined with Twitter Bootstrap.

Twitter Bootstrap example applications and tutorials from the RailsApps project:

Example App Tutorial Comments
Twitter Bootstrap, Devise, CanCan Tutorial Complete starter application
Startup Prelaunch Signup App Tutorial Capture emails for a site prelaunch
Rails Membership Site with Stripe Tutorial Site with subscription billing using Stripe
Rails Membership Site with Recurly Tutorial Site with subscription billing using Recurly

Installing Twitter Bootstrap

There are four steps to adding Twitter Bootstrap to a Rails application:

You’ll find full instructions below.

Twitter Bootstrap Gem

Twitter Bootstrap is best installed using one of several Ruby gems. Twitter Bootstrap can be installed using either its native LESS CSS language or the Sass language. Learn more from the article Twitter Bootstrap, Less, and Sass: Understanding Your Options for Rails 3.1.

Gem Author Comments
bootstrap-sass Thomas McDonald RECOMMENDED
sass-twitter-bootstrap John W. Long and others Sass
less-rails-bootstrap Ken Collins LESS
twitter-bootstrap-rails Seyhun Akyürek LESS

Sass is a default for CSS development in Rails so I recommend installing Thomas McDonald’s bootstrap-sass gem.

In your Gemfile, add:

gem 'bootstrap-sass'

and run $ bundle install.

Include the Twitter Bootstrap Javascript

Include the Twitter Bootstrap Javascript files by modifying the file app/assets/javascripts/application.js:

//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require_tree .

Using Sass

The Sass language is the default for CSS development in Rails.

It’s a good idea to rename the app/assets/stylesheets/application.css file as app/assets/stylesheets/application.css.scss.

This will allow you to use the advantages of the Sass syntax and features for your application stylesheet. For more on the advantages of Sass and how to use it, see the Sass Basics RailsCast from Ryan Bates.

Import the Twitter Bootstrap CSS

Next, import the Twitter Bootstrap CSS files. You can modify the app/assets/stylesheets/application.css.scss file to import Bootstrap. However, I recommend adding a new file app/assets/stylesheets/bootstrap_and_overrides.css.scss file. You may wish to modify the Twitter Bootstrap CSS rules; you can do so in the application.css.scss file but placing changes to Twitter Bootstrap CSS rules in the bootstrap_and_overrides.css.scss file will keep your CSS better organized.

The file app/assets/stylesheets/bootstrap_and_overrides.css.scss is automatically included and compiled into your Rails application.css file by the *= require_tree . statement in the app/assets/stylesheets/application.css.scss file.

Add the file app/assets/stylesheets/bootstrap_and_overrides.css.scss:

@import "bootstrap";
body { padding-top: 60px; }
@import "bootstrap-responsive";

The file will import both basic Bootstrap CSS rules and the Bootstrap rules for responsive design (allowing the layout to resize for various devices and secreen sizes).

The CSS rule body { padding-top: 60px; } applies an additional CSS rule to accommodate the “Bootstrap Navigation Bar” heading created by the navbar-fixed-top class in the header tag in the layout below.

Note: Prior to bootstrap-sass version 2.0.2, a bug required setting the iconSpritePath parameter. That is no longer necessary.

Finally, to provide an example of adding a CSS rule that will be used on every page of your application, the following code creates a nice gray box as a background to page content.

Add this to your app/assets/stylesheets/application.css.scss file for a gray background:

.content {
  background-color: #eee;
  padding: 20px;
  margin: 0 -20px; /* negative indent the amount of the padding to maintain the grid system */
  -webkit-border-radius: 0 0 6px 6px;
  -moz-border-radius: 0 0 6px 6px;
  border-radius: 0 0 6px 6px;
  -webkit-box-shadow: 0 1px 2px rgba(0,0,0,.15);
  -moz-box-shadow: 0 1px 2px rgba(0,0,0,.15);
  box-shadow: 0 1px 2px rgba(0,0,0,.15);
}

Default Application Layout

Generating a new Rails application with the rails new command will create a default application layout. Rails will use the layout defined in the file app/views/layouts/application.html.erb as a default for rendering any page. If you are using Haml, the file will be app/views/layouts/application.html.haml.

You’ll want to add navigation links, include flash messages for errors and notifications, and apply CSS styling using Twitter Bootstrap.

See the article HTML5 Boilerplate for Rails Developers for an explanation of what should be included in the default application layout.

Default Application Layout with Twitter Bootstrap (ERB)

Twitter Bootstrap provides additional elements for a more complex page layout.

Replace the contents of the file app/views/layouts/application.html.erb with this:

<!doctype html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= content_for?(:title) ? yield(:title) : "Myapp" %></title>
    <meta name="description" content="">
    <meta name="author" content="">
    <%= stylesheet_link_tag "application", :media => "all" %>
    <%= javascript_include_tag "application" %>
    <%= csrf_meta_tags %>
    <%= yield(:head) %>
  </head>
  <body>
    <header class="navbar navbar-fixed-top">
      <nav class="navbar-inner">
        <div class="container">
          <%= render 'layouts/navigation' %>
        </div>
      </nav>
    </header>
    <div id="main" role="main">
      <div class="container">
        <div class="content">
           <div class="row">
            <div class="span12">
              <%= render 'layouts/messages' %>
              <%= yield %>
            </div>
          </div>
          <footer>
          </footer>
        </div>
      </div> <!--! end of .container -->
    </div> <!--! end of #main -->
  </body>
</html>

Default Application Layout with Twitter Bootstrap (Haml)

If you are using Haml, remove app/views/layouts/application.html.erb and replace it with app/views/layouts/application.html.haml with the following content:

!!!
%html
  %head
    %meta{:charset => "utf-8"}
    %meta{:name => "viewport", :content => "width=device-width, initial-scale=1, maximum-scale=1"}
    %title= content_for?(:title) ? yield(:title) : "Myapp"
    %meta{:content => "", :name => "description"}
    %meta{:content => "", :name => "author"}
    = stylesheet_link_tag "application", :media => "all"
    = javascript_include_tag "application"
    = csrf_meta_tags
    = yield(:head)
  %body
    %header.navbar.navbar-fixed-top
      %nav.navbar-inner
        .container
          = render 'layouts/navigation'
    #main{:role => "main"}
      .container
        .content
          .row
            .span12
              = render 'layouts/messages'
              = yield
          %footer

Navigation Links

You’ll likely need navigation links on every page of your web application. You’ll want a link for Home. If you’ve implemented authentication using Devise you’ll want links for Login, Logout, and Sign Up. If you’re using OmniAuth for authentication, you’ll want links for Login and Logout. If you’ve got pages for an administrator, you may want a link for Admin.

You can add navigation links directly to your application layout file but many developers prefer to create a partial template – a “partial” – to better organize the default application layout.

Example Navigation Links for Devise (ERB)

Create the file app/views/layouts/_navigation.html.erb for the navigation links.

If you’re using Devise, use these navigation links:

<%= link_to "Home", root_path, :class => 'brand' %>
<ul class="nav">
  <% if user_signed_in? %>
    <li>
    <%= link_to('Logout', destroy_user_session_path, :method=>'delete') %>
    </li>
  <% else %>
    <li>
    <%= link_to('Login', new_user_session_path)  %>
    </li>
  <% end %>
  <% if user_signed_in? %>
    <li>
    <%= link_to('Edit account', edit_user_registration_path) %>
    </li>
  <% else %>
    <li>
    <%= link_to('Sign up', new_user_registration_path)  %>
    </li>
  <% end %>
</ul>

Example Navigation Links for Devise (Haml)

For Haml with Devise, create the file app/views/layouts/_navigation.html.haml:

= link_to "Home", root_path, :class => 'brand'
%ul.nav
  - if user_signed_in?
    %li
      = link_to('Logout', destroy_user_session_path, :method=>'delete')
  - else
    %li
      = link_to('Login', new_user_session_path)
  - if user_signed_in?
    %li
      = link_to('Edit account', edit_user_registration_path)
  - else
    %li
      = link_to('Sign up', new_user_registration_path)

Flash Messages with Twitter Bootstrap

Rails provides a standard convention to display alerts (including error messages) and other notices, called Rails “flash messages” (as in “flash memory”, not to be confused with the “Adobe Flash” proprietary web development platform).

You can include code to display flash messages directly in your application layout file or you can create a partial.

Rails uses :notice and :alert as flash message keys. Twitter Bootstrap provides a base class .alert with additional classes .alert-success and .alert-error (see the Bootstrap documentation on alerts). A bit of parsing is required to get a Rails “notice” message to be styled with the Twitter Bootstrap “alert-success” style. Any other message, including a Rails “alert” message, will be styled with the Twitter Bootstrap “alert-error” style.

Twitter Bootstrap provides a jQuery plugin named bootstrap-alert that makes it easy to dismiss flash messages with a click. The data-dismiss property displays an “x” that enables the close functionality. Note that Twitter Bootstrap uses the HTML entity “&#215;” instead of the keyboard letter “x”.

By default, Twitter Bootstrap applies a green background to .alert-success and a red background to .alert-error. Twitter Bootstrap provides a third class .alert-info with a blue background. With a little hacking, it’s possible to create a Rails flash message with a custom name, such as :info, that will display with the Bootstrap .alert-info class. However, it’s wise to stick with the Rails convention of using only “alert” and “notice.”

For an alternative that accommodates four different flash message types (success, error, alert, notice), see an example of Rails Flash Messages using Twitter Bootstrap.

Flash Messages with Twitter Bootstrap (ERB)

For CSS styling with Twitter Bootstrap, create a partial for flash messages in app/views/layouts/_messages.html.erb like this:

<% flash.each do |name, msg| %>
  <% if msg.is_a?(String) %>
    <div class="alert alert-<%= name == :notice ? "success" : "error" %>">
      <a class="close" data-dismiss="alert">&#215;</a>
      <%= content_tag :div, msg, :id => "flash_#{name}" %>
    </div>
  <% end %>
<% end %>

Flash Messages with Twitter Bootstrap (Haml)

For CSS styling with Twitter Bootstrap using Haml, create a partial for flash messages in app/views/layouts/_messages.html.haml like this:

- flash.each do |name, msg|
  - if msg.is_a?(String)
    %div{:class => "alert alert-#{name == :notice ? "success" : "error"}"}
      %a.close{"data-dismiss" => "alert"} ×
      = content_tag :div, msg, :id => "flash_#{name}"

Twitter Bootstrap provides a jQuery plugin named bootstrap-alert that makes it easy to dismiss flash messages with a click. The data-dismiss property displays an “x” that enables the close functionality. Note that Twitter Bootstrap uses the HTML entity “&#215;” instead of the keyboard letter “x”.

Form Builders

Most Rails applications use forms; most Rails developers use a form builder gem to simplify and improve upon the default Rails form helpers. Twitter Bootstrap provides styling for forms. Two popular form builder gems offer options to generate the markup required to display the Twitter Bootstrap form styling:

Gem Author
SimpleForm Plataformatec
Formtastic Justin French

I prefer SimpleForm.

Installing SimpleForm with Twitter Bootstrap

You’ll need the following gem in your Gemfile:

gem 'simple_form'

If you haven’t already, run:

$ bundle install

Run the generator to install SimpleForm with a Twitter Bootstrap option:

$ rails generate simple_form:install --bootstrap

which installs several configuration files:

config/initializers/simple_form.rb
config/initializers/simple_form_bootstrap.rb
config/locales/simple_form.en.yml
lib/templates/erb/scaffold/_form.html.erb

Base Errors Helper for SimpleForm

SimpleForm provides excellent handling of validation errors for any attributes of a model. However, some applications set model errors that are not matched to a specific form field. These are called “base errors.” For example, a model might set an error like this: errors.add :base, "Credit card declined". SimpleForm does not provide a helper to display base errors; if your application sets base errors, you’ll need to add the following view helper.

Add this view helper to app/helpers/application_helper.rb:

module ApplicationHelper

  def display_base_errors resource
    return '' if (resource.errors.empty?) or (resource.errors[:base].empty?)
    messages = resource.errors[:base].map { |msg| content_tag(:p, msg) }.join
    html = <<-HTML
    <div class="alert alert-error alert-block">
      <button type="button" class="close" data-dismiss="alert">&#215;</button>
      #{messages}
    </div>
    HTML
    html.html_safe
  end

end

Use the view helper in a form like this:

<%= simple_form_for ... %>
  <%= f.error_notification %>
  <%= display_base_errors resource %>
.
.
.
<% end %>

This extra helper is not needed in most applications; however, it can save time-consuming debugging for applications that use the errors.add :base method.

Options and Improvements

This introduction gives you the basics of Twitter Bootstrap with Rails, including messages for alerts and notices, and an application layout using Twitter Bootstrap.

There’s much more you can do with Twitter Bootstrap. For an advanced example, see the RailsApp rails-prelaunch-signup example app. The rails-prelaunch-signup tutorial shows how you can use Twitter Bootstrap to add a modal window and AJAX for a “sign up” form for a “Web 2.0” application. When the visitor submits the form, the modal window changes to display a “thank you” message (or an error message) without a page refresh.

Suggestions? Improvements? Please leave a comment.

Comments

Is this helpful? Your encouragement fuels the project. Please tweet or add a comment. Couldn't get something to work? For the example apps and tutorials, it's best to open an issue on GitHub so we can help you.

comments powered by Disqus