Jekyll Layouts

Episode #3 - Mar 11, 2016 - 7 minutes

Subscribe to Jekyll Casts

Most websites typically have a header and footer which remain similar across all the pages. If you compare this index.html file:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Home Page</title>
    <link rel="stylesheet" href="/css/style.css">
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,700" media="all">
  </head>
  <body>
    <header>
      <div class="container">
        <nav class="main-nav">
          <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog.html">Blog</a></li>
          </ul>
        </nav>
        <h1><a href="/">Bakery<strong>Store</strong></a></h1>
      </div>
    </header>
    <div class="content">
      <section class="hero">
        <div class="small-container">
          <h2>Fresh, homemade baked goods</h2>
          <p class="sub-text">Bakery<strong>Store</strong> serves the freshest baked goods in San Francisco.</p>
        </div>
      </section>
      <div class="container">
        <p class="post-hero center-text spacing">Bakery<strong>Store</strong> is known for our fresh bread, delicious cupcakes and chocolatey cookies.</p>
      </div>
      <div class="container">
        <div class="columns spacing">
          <div class="column half">
            <img src="/images/bread.jpg" width="430" alt="Bread">
          </div>
          <div class="column half">
            <h3>Fresh Bread</h3>
            <p>Our bread is baked fresh every morning.</p>
          </div>
        </div>
        <div class="columns spacing">
          <div class="column half">
            <h3>Delicious Cupcakes</h3>
            <p>The best cupcakes in San Francisco.</p>
          </div>
          <div class="column half">
            <img src="/images/cupcake.jpg" width="430" alt="cupcake">
          </div>
        </div>
        <div class="columns spacing">
          <div class="column half">
            <img src="/images/cookie.jpg" width="430" alt="cookie">
          </div>
          <div class="column half">
            <h3>Chocolatey cookies</h3>
            <p>Served with a glass of milk.</p>
          </div>
        </div>
      </div>
    </div>
    <footer>
      <div class="container">
        <p class="center-text"> <a href="http://cloudcannon.com">Created by CloudCannon</a></p>
      </div>
    </footer>
  </body>
</html>

You can see the content outside of the content div is almost exactly the same as blog.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Blog</title>
    <link rel="stylesheet" href="/css/style.css">
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,700" media="all">
  </head>
  <body>
    <header>
      <div class="container">
        <nav class="main-nav">
          <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog.html">Blog</a></li>
          </ul>
        </nav>
        <h1><a href="/">Bakery<strong>Store</strong></a></h1>
      </div>
    </header>
    <div class="content">
      <div class="container">
        <h2 class="spacing">Blog</h2>
        <div class="blog-posts">
          <div class="blog-post spacing">
            <h3><a href="/post.html">Where did the chocolate chip cookie come from?</a></h3>
            <p class="summary">Information<span class="date">January 02, 2016</span></p>
            <p>The chocolate chip cookie was invented by Ruth Graves Wakefield. She owned the Toll House Inn, in Whitman, Massachusetts, a very popular restaurant that featured home cooking in the 1930s. Her cookbook, Toll House Tried and True Recipes, was first published in 1936 by M. Barrows &amp; Company, New York. The 1938 edition of the cookbook was the first to include the recipe "Toll House Chocolate Crunch Cookie" which rapidly became a favorite cookie in American homes.</p>

            <p>Source / Read more <a href="https://en.wikipedia.org/wiki/Chocolate_chip_cookie">Wikipedia</a>.</p>
          </div>
          <div class="blog-post spacing">
            <h3><a href="/post.html">What is sour dough?</a></h3>
            <p class="summary">Information<span class="date">January 01, 2016</span></p>
            <p>Sourdough bread is made by the fermentation of dough using naturally-occurring lactobacilli and yeast. Sourdough bread has a mildly sour taste not present in most breads made with baker's yeast and better inherent keeping qualities than other breads, due to the lactic acid produced by the lactobacilli.</p>
            <p>Source / Read more <a href="https://en.wikipedia.org/wiki/Sourdough">Wikipedia</a>.</p>
          </div>
        </div>
      </div>
    </div>
    <footer>
      <div class="container">
        <p class="center-text"> <a href="http://cloudcannon.com">Created by CloudCannon</a></p>
      </div>
    </footer>
  </body>
</html>

In Jekyll we can use layouts to eliminate this repetition and make the site much easier to maintain.

To start with we’ll create a new directory called _layouts. Inside this we’ll create a new file called default.html. This file will contain the content which repeats across multiple pages.

Now we’ll cut all the HTML except the content div’s children from index.html and paste it into _layouts/default.html. We need a placeholder for where the content of the page is going to go. Jekyll makes this available to us using a content variable which we can output using Liquid.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Home Page</title>
    <link rel="stylesheet" href="/css/style.css">
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,700" media="all">
  </head>
  <body>
    <header>
      <div class="container">
        <nav class="main-nav">
          <ul>
            <li><a href="/">Home</a></li>
            <li><a href="/blog.html">Blog</a></li>
          </ul>
        </nav>
        <h1><a href="/">Bakery<strong>Store</strong></a></h1>
      </div>
    </header>
    <div class="content">
      {{ content }}
    </div>
    <footer>
      <div class="container">
        <p class="center-text"> <a href="http://cloudcannon.com">Created by CloudCannon</a></p>
      </div>
    </footer>
  </body>
</html>

Let’s use this layout on index.html. Jekyll front matter has a special variable called layout where we can specify a layout for this page. In this case we want index.html to use the default layout.

---
layout: default
---
<section class="hero">
  <div class="small-container">
    <h2>Fresh, homemade baked goods</h2>
    <p class="sub-text">Bakery<strong>Store</strong> serves the freshest baked goods in San Francisco.</p>
  </div>
</section>
<div class="container">
  <p class="post-hero center-text spacing">Bakery<strong>Store</strong> is known for our fresh bread, delicious cupcakes and chocolatey cookies.</p>
</div>
<div class="container">
  <div class="columns spacing">
    <div class="column half">
      <img src="/images/bread.jpg" width="430" alt="Bread">
    </div>
    <div class="column half">
      <h3>Fresh Bread</h3>
      <p>Our bread is baked fresh every morning.</p>
    </div>
  </div>
  <div class="columns spacing">
    <div class="column half">
      <h3>Delicious Cupcakes</h3>
      <p>The best cupcakes in San Francisco.</p>
    </div>
    <div class="column half">
      <img src="/images/cupcake.jpg" width="430" alt="cupcake">
    </div>
  </div>
  <div class="columns spacing">
    <div class="column half">
      <img src="/images/cookie.jpg" width="430" alt="cookie">
    </div>
    <div class="column half">
      <h3>Chocolatey cookies</h3>
      <p>Served with a glass of milk.</p>
    </div>
  </div>
</div>

Now when we load index.html it looks exactly as it did before, however now it’s powered by a layout. Let’s change blog.html to use the layout as well.

---
layout: default
---
<div class="container">
  <h2 class="spacing">Blog</h2>
  <div class="blog-posts">
    <div class="blog-post spacing">
      <h3><a href="/post.html">Where did the chocolate chip cookie come from?</a></h3>
      <p class="summary">Information<span class="date">January 02, 2016</span></p>
      <p>The chocolate chip cookie was invented by Ruth Graves Wakefield. She owned the Toll House Inn, in Whitman, Massachusetts, a very popular restaurant that featured home cooking in the 1930s. Her cookbook, Toll House Tried and True Recipes, was first published in 1936 by M. Barrows &amp; Company, New York. The 1938 edition of the cookbook was the first to include the recipe "Toll House Chocolate Crunch Cookie" which rapidly became a favorite cookie in American homes.</p>

      <p>Source / Read more <a href="https://en.wikipedia.org/wiki/Chocolate_chip_cookie">Wikipedia</a>.</p>
    </div>
    <div class="blog-post spacing">
      <h3><a href="/post.html">What is sour dough?</a></h3>
      <p class="summary">Information<span class="date">January 01, 2016</span></p>
      <p>Sourdough bread is made by the fermentation of dough using naturally-occurring lactobacilli and yeast. Sourdough bread has a mildly sour taste not present in most breads made with baker's yeast and better inherent keeping qualities than other breads, due to the lactic acid produced by the lactobacilli.</p>
      <p>Source / Read more <a href="https://en.wikipedia.org/wiki/Sourdough">Wikipedia</a>.</p>
    </div>
  </div>
</div>

In the next example let’s say we’re building multiple landing pages and they’re all going to have this hero section.

<section class="hero">
  <div class="small-container">
    <h2>Fresh, homemade baked goods</h2>
    <p class="sub-text">Bakery<strong>Store</strong> serves the freshest baked goods in San Francisco.</p>
  </div>
</section>

If we put this hero section in _layouts/default.html it’s going to output it on every page which we don’t want. We can use layout inheritance to get around this problem. We’ll start by creating a new layout, _layouts/page.html. In Jekyll, we can set a layout within a layout, so in the page layout we’ll have the hero section then it will call the default layout which has rest of the page structure.

---
layout: default
---
<section class="hero">
  <div class="small-container">
    <h2>Fresh, homemade baked goods</h2>
    <p class="sub-text">Bakery<strong>Store</strong> serves the freshest baked goods in San Francisco.</p>
  </div>
</section>
{{ content }}

Now we can use this layout on our landing pages and the hero section won’t be there on pages using the default layout.

In the last example we’ll use front matter to set the heading in the hero section so it can change on each page. In _layouts/page.html instead of <h2>Fresh, homemade baked goods</h2>, we’ll make it a variable:

---
layout: default
---
<section class="hero">
  <div class="small-container">
    <h2>{{ page.hero_text }}</h2>
    <p class="sub-text">Bakery<strong>Store</strong> serves the freshest baked goods in San Francisco.</p>
  </div>
</section>
{{ content }}

On our landing pages we can set hero_text in the front matter which will change the heading.

---
layout: page
hero_text: Home Page!
---
...

Hero Section

Another place this is useful is for setting page titles. We don’t want the title for each page to be “Home Page” so let’s change it to a variable in _layouts/default.html.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>{{ page.title }}</title>
    <link rel="stylesheet" href="/css/style.css">
    <link rel="stylesheet" href="http://fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,700" media="all">
  </head>
  ...

Then in on a page we can set a title in front matter:

---
layout: default
title: Blog
---
...

There’s a one minor difference between Jekyll 2 and 3 in regards to layouts. If we set front matter inside a layout, for example in _layouts/page.html let’s say we have this:

---
layout: default
city: San Francisco
---
<section class="hero">
  <div class="small-container">
    <h2>{{ page.hero_text }}</h2>
    <p class="sub-text">Bakery<strong>Store</strong> serves the freshest baked goods in San Francisco.</p>
  </div>
</section>
{{ content }}

In Jekyll 2 we could output city using the page variable like this:

{{ page.city }}

In Jekyll 3 we would output city using the layout variable like this:

{{ layout.city }}

Subscribe to Jekyll Casts