Skip to content

rails default application layout

Daniel Kehoe edited this page Dec 8, 2013 · 44 revisions

Rails Application Layout

by Daniel Kehoe

Last updated 7 December 2013

Rails application layout for HTML5. Shows how to set up an application layout with navigation links, messages for alerts and notices, and CSS styling for Rails 4.0.

If You Are New to Rails

If you’re new to Rails, see What is Ruby on Rails?, the book Learn Ruby on Rails, and recommendations for a Rails tutorial.

Learn Ruby on Rails

What is the RailsApps Project?

This is an article from the RailsApps project. The RailsApps project provides example applications that developers use as starter apps. Hundreds of developers use the apps, report problems as they arise, and propose solutions. Rails changes frequently; each application is known to work and serves as your personal “reference implementation” so you can stay up to date. Each is accompanied by a tutorial so there is no mystery code. Support for the project, including the example applications and the Rails Composer tool, comes from subscribers to the RailsApps tutorials.

Background

Every Rails application needs a well-designed application layout. The Rails default starter application, which is created when you run rails new, provides a barebones application layout. You’ll want to add navigation links, include flash messages for errors and notifications, and apply CSS styling.

Rails will use the layout defined in the file app/views/layouts/application.html.erb as a default for rendering any page. See the RailsGuide Layouts and Rendering in Rails for details. The book Learn Ruby on Rails provides an in-depth explanation.

This article shows how to set up a simple application layout with navigation links, messages for alerts and notices, and CSS styling for Rails 4.0. If you intend to use a front-framework such as Twitter Bootstrap or Zurb Foundation, see these articles for specifics:

This article shows how to use the rails_layout gem to generate files for an application layout, navigation links, and flash messages styled with simple CSS classes and layout.

Rails Default Application Layout

This is the default application layout created by the rails new command with Rails 4.0:


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.

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>

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

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.

ERB

For simple CSS styling, 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) %>
    <%= content_tag :div, msg, :id => "flash_#{name}" %>
  <% end %>
<% end %>

Haml

For 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)
    = content_tag :div, msg, :id => "flash_#{name}"

Flash Messages with Twitter Bootstrap

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.”

ERB (Twitter Bootstrap)

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 %>

Haml (Twitter Bootstrap)

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}"

CSS Styling

Twitter Bootstrap and other CSS front-end frameworks (such as Zurb Foundation) are toolkits that provide the kind of structure and convention for the front end that make Rails popular for server-side (“back-end”) development. You can use Twitter Bootstrap to quickly add attractive CSS styling to your application. If you’ve generated your app using the Rails Composer tool (“like the ‘rails new’ command on steroids”), the program will offer to install Twitter Bootstrap or other CSS front-end frameworks and set up your default application layout accordingly.

Use SASS

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.

Simple CSS Styling

If you don’t want to use Twitter Bootstrap or another CSS front-end framework, you can apply simple CSS styling for your navigation links and flash messages with the following code.

Add stylesheet rules to the app/assets/stylesheets/application.css.scss file:

.brand {
  float: left;
  padding-right: 8px;
}
ul.nav {
  list-style: none;
  margin: 0 0 2em;
  padding: 0;
}
ul.nav li {
  display: inline;
}
#flash_notice, #flash_alert {
  padding: 5px 8px;
  margin: 10px 0;
}
#flash_notice {
  background-color: #CFC;
  border: solid 1px #6C6;
}
#flash_alert {
  background-color: #FCC;
  border: solid 1px #C66;
}

CSS Styling with Twitter Bootstrap (Sass)

It’s easy to use the Rails Composer tool to install Twitter Bootstrap and set up your default application layout. If you’re building an app step-by-step without using the program, here are instructions for setting up Twitter Bootstrap.

Several options are available for installing Twitter Bootstrap in a Rails application. Twitter Bootstrap can be installed using either its native LESS CSS language or the SASS language that is the default for CSS files in Rails. See the article Twitter Bootstrap, Less, and Sass: Understanding Your Options for Rails 3.1. SASS is a default for CSS development in Rails so I recommend you install Thomas McDonald’s bootstrap-sass gem.

In your Gemfile, add:

gem 'bootstrap-sass'

and run $ bundle install.

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

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

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 black 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);
}

Using mixins from the bootstrap-sass gem, you can simplify this:

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

Head Additions

Rails provides a skeletal head section for an application layout:

<head>
  <title>App_Name</title>
  <%= stylesheet_link_tag "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
</head>

Here are other elements you may wish to add:

<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title><%= content_for?(:title) ? yield(:title) : "App_Name" %></title>
  <meta name="description" content="<%= content_for?(:description) ? yield(:description) : "App_Name" %>">
  <%= stylesheet_link_tag "application", :media => "all" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>
  <%= yield(:head) %>
</head>

Viewport

Apple introduced the viewport metatag to help web developers improve the presentation of web pages on mobile devices. Setting a viewport tells the browser how content should fit on the device’s screen. See Apple’s developer documentation on Configuring the Viewport for all the details. You’ll need to set the viewport to make full use of responsive front-end frameworks such as Twitter Bootstrap or Zurb Foundation.

Title and Description

Google uses contents of the title tag to display titles in search results. And it will sometimes use content of a description meta tag in search results snippets. See Google’s explanation of how it uses Site Title and Description. Good titles and descriptions improve clickthrough from Google searches. Use a content_for statement in a specific view to set a title and description for a page. Google likes distinct titles and unique descriptions for each page on your site.

Using Content_for with Yield

The combination of content_for? with yield allows you to inject data into the application layout from any view. Set up a view file containing the code:

<% content_for :title do %>My Title<% end %>
<% content_for :description do %>My Description<% end %>

When a controller renders the view template and combines it with the application layout, the text “My Title” will replace <%= content_for?(:title) ? yield(:title) : "App_Name" %> in the application layout. If no content_for block is found in the view template, the alternate text “App_Name” will be used.

Yield Head

The statement <%= yield(:head) %> makes it easy to add more head elements if needed for a specific page.

Some developers use this for adding additional JavaScript scripts but other techniques are better. See the article Adding JavaScript to Rails for details.

The Body Tag

The simplest form of the <body> tag is all you need for many applications. However, if you’re using JavaScript extensively and wish to execute JavaScript conditionally on a page, it’s helpful to set the controller name and action in the <body> tag:

<body class="<%= controller_name %> <%= action_name %>">

See the article Adding JavaScript to Rails for details.

Default Application Layout (for Rails 3.1 and newer)

Generating a new Rails application with the rails new command will create a default application layout in the file app/views/layouts/application.html.erb. Modify the file to add navigation links, include flash messages, and apply CSS styling.

Use the code below to incorporate recommendations from the article HTML5 Boilerplate for Rails Developers.

This application layout accommodates simple CSS styling. For Twitter Bootstrap, see a more complex application layout following this code.

Simple Default Application Layout (ERB)

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

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= content_for?(:title) ? yield(:title) : "App_Name" %></title>
    <meta name="description" content="<%= content_for?(:description) ? yield(:description) : "App_Name" %>">
    <%= stylesheet_link_tag "application", :media => "all" %>
    <%= javascript_include_tag "application" %>
    <%= csrf_meta_tags %>
    <%= yield(:head) %>
  </head>
  <body class="<%= controller_name %> <%= action_name %>">
    <div id="container" class="container">
      <header>
        <%= render 'layouts/navigation' %>
        <%= render 'layouts/messages' %>
      </header>
      <div id="main" role="main">
        <%= yield %>
      </div>
      <footer>
      </footer>
    </div> <!--! end of #container -->
  </body>
</html>

Simple Default Application Layout (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{:name => "viewport", :content => "width=device-width, initial-scale=1, maximum-scale=1"}
    %title= content_for?(:title) ? yield(:title) : "App_Name"
    %meta{:content => content_for?(:description) ? yield(:description) : "App_Name", :name => "description"}
    = stylesheet_link_tag :application, :media => "all"
    = javascript_include_tag :application
    = csrf_meta_tags
    = yield(:head)
  %body
    #container.container
      %header
        = render 'layouts/navigation'
        = render 'layouts/messages'
      #main{:role => "main"}
        = yield
      %footer

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 name="viewport" content="width=device-width, initial-scale=1.0">
    <title><%= content_for?(:title) ? yield(:title) : "App_Name" %></title>
    <meta name="description" content="<%= content_for?(:description) ? yield(:description) : "App_Name" %>">
    <%= stylesheet_link_tag "application", :media => "all" %>
    <%= javascript_include_tag "application" %>
    <%= csrf_meta_tags %>
    <%= yield(:head) %>
  </head>
  <body class="<%= controller_name %> <%= action_name %>">
    <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{:name => "viewport", :content => "width=device-width, initial-scale=1, maximum-scale=1"}
    %title= content_for?(:title) ? yield(:title) : "App_Name"
    %meta{:content => content_for?(:description) ? yield(:description) : "App_Name", :name => "description"}
    = 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

Options and Improvements

Your default application layout defines the look-and-feel of your application. This introduction gives you the basics with navigation links, messages for alerts and notices, and CSS styling (including using Twitter Bootstrap).

There’s much more you can do. 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.

Clone this wiki locally