Skip to content

Rails Layouts and Partials — Reusable View Components

DodaTech Updated 2026-06-28 3 min read

In this tutorial, you will learn about Rails Layouts and Partials. We cover key concepts, practical examples, and best practices to help you master this topic.

Rails layouts and partials enable reusable view components with layout inheritance, nested layouts, shared partials across controllers, and content_for blocks for dynamic content.

What You'll Learn

By the end of this tutorial, you'll create application layouts with nested content, use content_for blocks, render partials with locals, create shared partials, and organize template inheritance.

Why Layouts and Partials Matter

Layouts provide consistent page structure. Partials eliminate duplicated HTML. Together they keep views DRY and maintainable.

Real-World Use

An admin panel uses a different layout than the public site. Both layouts include shared partials for navigation and footer. Each layout yields content_for blocks for page-specific scripts.

Layouts Path

flowchart LR
  A[Rails Views] --> B[Layouts Partials]
  B --> C[Layout Inheritance]
  B --> D[Content For]
  B --> E[Shared Partials]
  B --> F[Nested Layouts]
  B --> G{You Are Here}
  style G fill:#f90,color:#fff

Application Layout

The default layout for all views.

<%# views/layouts/application.html.erb %>
<!DOCTYPE html>
<html>
<head>
  <title><%= content_for?(:title) ? yield(:title) : "My App" %></title>
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <%= csrf_meta_tags %>
  <%= csp_meta_tag %>
  <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  <%= javascript_importmap_tags %>
</head>
<body>
  <%= render "layouts/navigation" %>
  <main class="container">
    <%= render "layouts/flash_messages" %>
    <%= yield %>
  </main>
  <%= render "layouts/footer" %>
</body>
</html>

Nested Layouts

Use different layouts per controller.

# app/controllers/admin_controller.rb
class AdminController < ApplicationController
  layout "admin"
end
<%# views/layouts/admin.html.erb %>
<% content_for :head do %>
  <%= stylesheet_link_tag "admin" %>
<% end %>
<div class="admin-layout">
  <aside><%= render "admin/sidebar" %></aside>
  <main><%= yield %></main>
</div>
<%= render template: "layouts/application" %>

Partials with Locals

Pass variables to partials.

<%# views/products/show.html.erb %>
<%= render "product_card", product: @product, show_details: true %>

<%# views/products/index.html.erb %>
<%= render partial: "product_card", collection: @products, as: :product, locals: { show_details: false } %>
<%# views/products/_product_card.html.erb %>
<div class="product-card">
  <h3><%= link_to product.name, product %></h3>
  <p><%= number_to_currency(product.price) %></p>
  <% if local_assigns[:show_details] %>
    <p><%= product.description %></p>
    <%= link_to "Edit", edit_product_path(product) %>
  <% end %>
</div>

Counter and Iteration

Built-in counter variables in partial collections.

<%# views/products/index.html.erb %>
<%= render partial: "product_row", collection: @products %>

<%# views/products/_product_row.html.erb %>
<tr class="<%= product_row_counter.even? ? "even" : "odd" %>">
  <td><%= product_row_counter + 1 %></td>
  <td><%= product_row.name %></td>
  <td><%= number_to_currency(product_row.price) %></td>
  <td>
    <% if product_row_iteration.first? %>
      <span class="badge">New</span>
    <% end %>
    <% if product_row_iteration.last? %>
      <span class="badge">Last</span>
    <% end %>
  </td>
</tr>

Common Mistakes

1. Hardcoding Layout Names in Actions

Use layout :name in the controller instead of render layout: "name" in each action.

2. Not Using Content For for Page-Specific Assets

Adding scripts and styles inline instead of content_for blocks clutters the head.

3. Over-Nesting Partials

Partials calling partials calling partials becomes unmanageable. Limit nesting to 2-3 levels.

4. Using @ Variables in Partials

Partials should receive locals, not depend on controller instance variables.

5. Not Using Render Collection for Lists

Manually iterating with each in a partial is slower than render collection.

Practice Questions

1. How do you specify a different layout for a controller?

Use layout "admin" in the controller class definition.

2. What is a nested layout?

A layout that wraps another layout. The inner layout yields to the outer layout.

3. How do you pass local variables to a partial?

Use locals: { key: value } in the render call.

4. What are counter variables in partials?

product_row_counter and product_row_iteration provide index and iteration metadata.

5. Challenge: Create an admin layout with sidebar and nested content.

<%# views/layouts/admin.html.erb %>
<% content_for :head, stylesheet_link_tag("admin") %>
<div class="admin-wrapper">
  <nav><%= render "admin/sidebar" %></nav>
  <main><%= yield %></main>
</div>
<%= render template: "layouts/application" %>

FAQ

What is the default layout?

views/layouts/application.html.erb.

Can I have multiple layouts?

Yes. Define different layouts in views/layouts/ and specify which controller uses which.

How do partials find templates?

Partials look in the same controller's view directory first, then views/application/.

What is the difference between render and partial?

render renders a template. partial: renders a partial. Both use the render method.

Can layout files use partials?

Yes. Layouts commonly render partials for nav, footer, and flash messages.

Mini Project: Two-Layout Application

Build an application with public and admin layouts.

class ApplicationController < ActionController::Base
  layout :layout_by_resource

  private

  def layout_by_resource
    if devise_controller? && resource_name == :admin
      "admin"
    else
      "application"
    end
  end
end

What's Next

Rails Helpers Rails Partials Collections Rails Views Deep

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro