Layouts

Exercises

Objective

Every good web app has some sort of consistent layout across all the pages: a header at the top, a footer at the bottom, and perhaps even a sidebar next to the main content. What's considered fashionable in terms of shapes, sizes, colors, and other design choices tends to change (usually about the time you launch your app). But when it comes to the layout of your app, consistency never goes out of style.

And to keep things consistent, we need to be able to put all the common layout elements in one definitive place. In Rails, that's called the layout file. A layout file is just a regular ERb view template that "wraps" the other view templates in the application. In other words, the layout generates HTML for the header, footer, and sidebar that surrounds the HTML generated by an action's view template. That way, we end up with a complete HTML document to send back to the browser. By having the layout in a single file, we can easily change the layout of our app.

We've gotten this far using the default HTML layout that was generated by Rails. That helped us get an app up and running quickly. Now it's time to start customizing the layout to better suit our app.

This turns out to be a fairly easy exercise. So let's jump right into it!

1. Review the Default Layout

Let's start by reviewing what we get for free...

  1. Open the default layout file in app/views/layouts/application.html.erb and you should see the following:

    <!DOCTYPE html>
    <html>
      <head>
        <title>Flix</title>
        <%= csrf_meta_tags %>
        <%= csp_meta_tag %>
    
        <%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
        <%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
      </head>
    
      <body>
        <%= yield %>
      </body>
    </html>
    

    Notice that the layout file is a mix of HTML and ERb tags, just like a regular view template.

  2. To see what it generates, browse to any page in the app and view the generated source. What you'll see is the HTML that was generated by a particular view template, index for example, is surrounded by the HTML generated by the layout template. Let's unpack how that happens.

    Back in the layout file, at the top you'll find a few built-in helpers that we haven't seen before:

    • stylesheet_link_tag generates the following link tags for the app's stylesheets, which we'll explore in the next section:

      <link rel="stylesheet" media="all" href="/assets/movies.self-e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855.css?body=1" data-turbolinks-track="reload" />
      <link rel="stylesheet" media="all" href="/assets/application.self-f0d704deea029cf000697e2c0181ec173a1b474645466ed843eb5ee7bb215794.css?body=1" data-turbolinks-track="reload" />
      
    • javascript_pack_tag generates the following script tag for the JavaScript file used by the app (beyond the scope of this course):

      <script src="/packs/js/application-4e793d3ebc7e69100513.js" data-turbolinks-track="reload"></script>
      
    • csrf_meta_tags generates meta tags for a token that's used internally by Rails to add hidden security fields to forms (don't worry about it):

      <meta name="csrf-param" content="authenticity_token" />
      <meta name="csrf-token" content="1jqaq6EPjEq6/e/nkhoL3czTGNIiYmOmIQq32yLl8GUqjp2X3GDkLkDhgyKmqVD7HDzzcEyG53HYLfbPQknJkA==" />
      
    • csp_meta_tag generates meta tag for a per-session nonce value for allowing inline <script> tags (don't worry about it either).

    So far, so good. That's all fairly straight-forward.

    Next comes the most non-intuitive part of the layout, which is also the most important part:

    <%= yield %>
    

    The yield returns the output (HTML) that an action generates. That output is then substituted right into the layout file because the <%= %> ERb tag was used. For example, if you visit the index page, the yield line in the layout file is replaced by the HTML that the index.html.erb template generates:

    <ul>
      <li>
        <strong>Iron Man</strong> (PG-13): $585,366,247
        ...
      </li>
      ...
    </ul>
    

    So whichever page you visit, the main content changes but the surrounding layout remains consistent. That's the essence of a layout file!

  3. Just as a quick test, go ahead and change the contents of the title tag to a custom name for your app. Then refresh and you should see the new page title appear at the top of your browser window for every page in the app.

    Show Answer

    Hide Answer

    <title>Super-Heroic Flix</title>
    

2. Add a Header and Footer

Now let's start customizing. To keep the marketing folks happy, each page needs some marquee header text at the top. And to keep the legal folks happy (a tall order), each page needs a footer at the bottom with a copyright.

  1. Inside the body tag, start by adding a header element above the main content. Inside the header, display the name of the app in an h1 tag.

    Show Answer

    Hide Answer

    <header>
      <h1>Flix</h1>
    </header>
    
  2. Next, put the yield line in a div with the class of content, like so:

    <div class="content">
      <%= yield %>
    </div>
    
  3. Finally, add a footer element below the main content and inside the footer display a copyright notice and a link back to your company. Want to keep your copyright year up to date? No problem! Just use Time.now.year to display the current year.

    Show Answer

    Hide Answer

    <footer>
      <p>
        Copyright &copy; 2005-<%= Time.now.year %>
        <%= link_to 'The Pragmatic Studio','https://pragmaticstudio.com' %>
      </p>
    </footer>
    

    Here's the final, full layout file:

    Show Answer

    Hide Answer

    <!DOCTYPE html>
    <html>
    <head>
      <title>Super-Heroic Flix</title>
      ...
    </head>
    <body>
    
      <header>
        <h1>Flix</h1>
      </header>
    
      <div class="content">
        <%= yield %>
      </div>
    
      <footer>
        <p>
          Copyright &copy; <%= Time.now.year %>
          <%= link_to 'The Pragmatic Studio','https://pragmaticstudio.com' %>
        </p>
      </footer>
    
    </body>
    </html>
    
  4. Then browse to http://localhost:3000/movies and you should see the header text at the top, the result of calling the index action in the middle, and the footer text at the bottom.

And now you have a consistent layout that will get applied to every page of the application! This will become really convenient as we add more pages in upcoming exercises.

Solution

The full solution for this exercise is in the layouts directory of the code bundle.

Wrap Up

And that's all there really is to layouts! They're just regular ERb templates that "wrap" the other view templates so your application is displayed in a consistent layout.

Structuring the app around a basic layout is a good start. But once you've been introduced to the layout file, you start thinking about colors, sizes, fonts, and so on. Yup, this is the point where application development crosses over into web design. That's a huge topic that's beyond the scope of this course, but in the next section we'll have a quick look at styling the app with CSS and images.

Dive Deeper

The application.html.erb layout file is the application-wide layout. By default, it's applied to every action in the application. But Rails offers lots of options for rendering a custom layout file depending on the controller, action, or even arbitrary application logic. To learn more about custom layouts, refer to 2.2.13 Finding Layouts in the Rails Guide: Layouts and Rendering.