Layouts

When Rails renders a view as a response, it does so by combining the view with the current layout. A layout defines the surroundings of an HTML page. It’s the place to define a common look and feel of your final output.

By default, Rails uses the app/views/layouts/application.html.erb file as the main layout. It is created when you create a new ails application.

If you create a library application with rails new library command, its main layout code would be as follows:

<!DOCTYPE html><html><head><title><%= content_for(:title) || "library" %></title><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="mobile-web-app-capable" content="yes">
&lt;%= csrf_meta_tags %&gt;
&lt;%= csp_meta_tag %&gt;
&lt;%= yield :head %&gt;
&lt;%# Enable PWA manifest for installable apps (make sure to enable in config/routes.rb too!) %&gt;
&lt;%#= tag.link rel: "manifest", href: pwa_manifest_path(format: :json) %&gt;
&lt;link rel="icon" href="/icon.png" type="image/png"&gt;&lt;link rel="icon" href="/icon.svg" type="image/svg+xml"&gt;&lt;link rel="apple-touch-icon" href="/icon.png"&gt;
&lt;%# Includes all stylesheet files in app/assets/stylesheets %&gt;
&lt;%= stylesheet_link_tag :app, "data-turbo-track": "reload" %&gt;
&lt;%= javascript_importmap_tags %&gt;
</head><body>
&lt;%= yield %&gt;
</body></html>

The main aspects of this layout code are:

  • Asset tags
  • yield and content_for
  • Partials

Asset Tags

These tags generate HTML to create links to different resources such as JavaScript and CSS scripts, images etc.

The stylesheet_link_tag helper returns an HTML <link> tag for each source provided. In the above code, the statement

<%= stylesheet_link_tag :app, "data-turbo-track": "reload" %>

generates a link to /assets/stylesheets/app.css

Similarly, the statement such as,

<%= javascript_include_tag "main"%>

Outputs a script tag as follows:

<script src='app/assets/javascripts/main.js'></script>

The yield Tag

The application.html.erb file acts as a base template used by the individual view templates. For example, the index action in the BooksController renders the index.html.erb view. The tag <%= yield %> inside application.html.erb marks a section where content from the view should be inserted.

This can be verified by looking at the log generated on the command terminal when you start the server and visit the index view (http://localhost:3000/books/)

StartedGET"/books"for::1 at 2025-03-2500:11:13+0530Processing by BooksController#index as HTMLRendering layout layouts/application.html.erb
  Rendering books/index.html.erb within layouts/application
  BookLoad(4.3ms)SELECT"books".*FROM"books"/*action='index',application='Controllerdemo',controller='books'*/
  ↳ app/views/books/index.html.erb:1Rendered books/index.html.erb within layouts/application (Duration:14.6ms |GC:0.0ms)Rendered layout layouts/application.html.erb (Duration:519.7ms |GC:0.3ms)Completed200OKin2448ms (Views:518.6ms |ActiveRecord:4.3ms (1 query,0 cached)|GC:0.3ms)

Rails first renders the application layout and then renders the index.html.erb inside it. Thus the yield tag is a place holder for the output of the view to be inserted.

Let us assume that the Rails application has a BooksController with index and show actions, A book model that has been migrated and a few book records already entered.

classBooksController<ApplicationControllerdefindex@books=Book.all
  end

The index action renders the index view (index.html.erb):

<% if @books.blank? %>
<p>There are not any books currently in the system.</p>
<% else %>
<p>These are the current books in our system</p><ul id = "books">
   <% @books.each do |c| %>
   <li><%= link_to c.title, {:action => 'show', :id => c.id} -%></li>
   <% end %>
</ul>

<% end %>
<p><%= link_to "Add new Book", {:action => 'new' }%></p>

The following figure shows the output of index view when the default application layout is used.

The yield Tag

Changing the Default Layout

Let us now change the default layout. Save the following code to app\views\layouts\standard.html.erb.

<!DOCTYPE html PUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns ="http://www.w3.org/1999/xhtml"><head><meta http-equiv ="Content-Type" content ="text/html; charset = iso-8859-1"/><meta http-equiv ="Content-Language" content ="en-us"/><title>LibraryInfoSystem</title></head><body id ="library"><div id ="container"><div id ="header"><h1>LibraryInfoSystem</h1><h3>Library powered by Ruby on Rails</h3></div><div id ="content"><%= yield -%>
     &lt;/div&gt;
     &lt;div id ="sidebar"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/body&gt;&lt;/html&gt;</pre>

You let the controllers know what template to use by the name of the file, so following a same naming scheme is advised. Now open books_controller.rb and add layout command to specify the layout to be used.

classBooksController<ApplicationController
  layout "standard"defindex@books=Book.all
  end

It instructs the controller that we want to use a layout available in the standard.html.erb file. Now try browsing books that will produce the following screen. Restart the server and visit the index view. The browser shows the following output.

Changing the Default Layout

The command terminal log also confirms that the standard layout is in use.

Rendered books/index.html.erb within layouts/standard (Duration:6.9ms |GC:0.0ms)Rendered layout layouts/standard.html.erb (Duration:9.0ms |GC:0.0ms)

Adding the Style Sheet

Till now, we have not created any style sheet, so Rails is using the default style sheet. Now let's create a new file called style.css and save it in /public/stylesheets. Add the following code to this file.

body {
font-family: Helvetica, Geneva, Arial, sans-serif;
font-size: small;
color: #000;
background-color: #fff;
} a:link, a:active, a:visited {
color: #CD0000;
} input {
margin-bottom: 5px;
} p {
line-height: 150%;
} div#container {
width: 760px;
margin: 0 auto;
} div#header {
text-align: center;
padding-bottom: 15px;
} div#content {
float: left;
width: 450px;
padding: 10px;
} div#content h3 {
margin-top: 15px;
} ul#books {
list-style-type: none;
} ul#books li {
line-height: 140%;
} div#sidebar {
width: 200px;
margin-left: 480px;
} ul#subjects {
width: 700px;
text-align: center;
padding: 5px;
background-color: #ececec;
border: 1px solid #ccc;
margin-bottom: 20px;
} ul#subjects li {
display: inline;
padding-left: 5px;
}

Now refresh your browser and see the difference −

Adding the Style Sheet

You can also create a layout with multiple yielding regions:

<html><head>
&lt;%= yield :head %&gt;
</head><body>
&lt;%= yield %&gt;
</body></html>

The main body of the view will always render into the unnamed yield. To render content into a named yield, call the content_for method with the same argument as the named yield.

Using Partials

Rails supports Partial templates - usually just called "partials" are reusable components stored in files prefixed with an underscore (_).

Let us add a navbar to the standard layout. For this purpose, first save the following HTML as _navbar.html.erb in app\views\books folder

<nav><ul class="horizontal-navbar"><li><a href="/">Home</a></li><li><a href="/show">Show</a></li></ul></nav>

To render a partial as part of a view, you use the render method inside the standard layout. Here, the navbar is to be displayed on the top, so add the following stamen in the <head> section.

<%= render "navbar" %>

This will render a file named _navbar.html.erb at that point within the view being rendered. Note the leading underscore character: partials are named with a leading underscore to distinguish them from regular views, even though they are referred to without the underscore.

You may have to update the style.css to include the navbar styles.

.horizontal-navbar {
   list-style-type: none;
   padding: 0;
   margin: 0;
   display: flex;
 }
 
 .horizontal-navbar li {
   margin-right: 20px;
 }
 
 .horizontal-navbar li a {
   text-decoration: none;
   color: black;
 }

Save the changes and refresh the browser. The index view now displays the navbar at the top as a result of including the partial template.

Using Partials

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *