Skip to content

Ruby on Rails - Layouts

Layouts in Rails define the common structure surrounding your views. They allow you to have a consistent header, footer, navigation, and overall look and feel across multiple pages of your application. Layout files reside in app/views/layouts/.

By default, Rails uses a layout file named application.html.erb. When a controller action renders a view, Rails wraps that view’s content within this layout.

Let’s create a custom layout for our library application. We’ll name it library_layout.html.erb and place it in app/views/layouts/.

Add the following HTML and ERB code to app/views/layouts/library_layout.html.erb:

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Library Info System</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag "application", media: "all", "data-turbo-track": "reload" %>
<%= javascript_include_tag "application", "data-turbo-track": "reload", defer: true %>
</head>
<body id="library-app">
<div id="container">
<header id="main-header">
<h1>Library Information System</h1>
<h3>Powered by Ruby on Rails</h3>
</header>
<nav id="main-nav">
<!-- Navigation links can go here -->
<%= link_to "Home (Books List)", books_path %>
</nav>
<main id="content">
<%# Display flash messages %>
<% flash.each do |type, msg| %>
<div class="alert alert-<%= type %>"><%= msg %></div>
<% end %>
<%= yield %> <%# This is where the content of individual views will be inserted %>
</main>
<aside id="sidebar">
<!-- Sidebar content can go here -->
<h4>Subjects</h4>
<ul id="subjects-sidebar">
<%# You might load @subjects here if available globally or via a helper %>
<%# Subject.all.each do |subject| %>
<%# content_tag :li, link_to(subject.name, subject_path(subject)) %>
<%# end %>
</ul>
</aside>
<footer id="main-footer">
<p>&copy; <%= Time.now.year %> Library Info System</p>
</footer>
</div>
</body>
</html>

Key elements in this layout:

  • <!DOCTYPE html>: Standard HTML5 doctype.
  • <meta charset="utf-8"> and <meta name="viewport" ...>: Essential meta tags.
  • csrf_meta_tags and csp_meta_tag: Security-related helpers provided by Rails.
  • stylesheet_link_tag "application", ...: Includes your application’s compiled CSS (managed by Sprockets or Webpacker/Shakapacker via app/assets/stylesheets/application.css or similar).
  • javascript_include_tag "application", ...: Includes your application’s compiled JavaScript.
  • <%= yield %>: This is the most important part. It’s where the content from your specific view (e.g., index.html.erb, show.html.erb) will be rendered.
  • Flash messages: A common pattern to display informational messages or errors to the user.
  • Navigation, header, footer, sidebar: Common structural elements.

To tell your BooksController (or any other controller) to use this new layout, you can specify it at the top of the controller file:

app/controllers/books_controller.rb
class BooksController < ApplicationController
layout 'library_layout'
def index
@books = Book.all
# Assuming you want to show all subjects in the sidebar of the layout
# This is just one way; helpers or before_actions are also options for shared data
@all_subjects_for_layout = Subject.order(:name)
end
# ... other actions ...
end

If you want all controllers in your application to use this layout by default, you can rename library_layout.html.erb to application.html.erb, or specify it in ApplicationController:

app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
layout 'library_layout'
end

Now, when you browse pages handled by BooksController, they will be rendered within the library_layout.html.erb structure.

Styles for your application are typically managed in app/assets/stylesheets/. The application.css (or application.scss/application.sass) file often acts as a manifest, importing other stylesheets.

Create or edit app/assets/stylesheets/application.css (or a new file like custom_styles.css and import it into application.css using *= require custom_styles).

/* Example styles for app/assets/stylesheets/custom_styles.css */
body#library-app {
font-family: Helvetica, Geneva, Arial, sans-serif;
font-size: medium;
color: #333;
background-color: #f4f4f4;
margin: 0;
padding: 0;
}
#container {
width: 960px;
margin: 20px auto;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0,0,0,0.1);
}
#main-header h1, #main-header h3 {
text-align: center;
color: #2c3e50;
}
#main-header h1 { margin-bottom: 0; }
#main-header h3 { margin-top: 5px; color: #7f8c8d; }
#content {
padding: 15px;
min-height: 300px; /* Example */
}
/* Add more specific styles for your elements */
ul#books, ul#subjects-sidebar {
list-style-type: none;
padding-left: 0;
}
ul#books li, ul#subjects-sidebar li {
line-height: 1.6;
margin-bottom: 5px;
padding: 5px;
border-bottom: 1px dotted #eee;
}
.alert {
padding: 10px;
margin-bottom: 15px;
border: 1px solid transparent;
border-radius: 4px;
}
.alert-notice { background-color: #dff0d8; border-color: #d6e9c6; color: #3c763d; }
.alert-alert { background-color: #f2dede; border-color: #ebccd1; color: #a94442; }

Ensure this CSS is processed by Sprockets (or your chosen asset pipeline tool). If you created custom_styles.css, make sure app/assets/stylesheets/application.css includes it, for example, with *= require custom_styles if application.css is a manifest file, or @import "custom_styles"; if application.scss.

Refreshing your browser after adding styles should show the application with the new look and feel defined by your layout and CSS.

Layouts provide a consistent shell. The next chapter discusses Scaffolding, a Rails feature that can quickly generate a full set of model, views, controller, and routes for a resource, which can be a great starting point or learning tool.