Jekyll & Liquid Tags: A Dynamic Duo

Earlier this morning I made some slight design tweaks to the way the page headers are displayed. Before, each page (excluding blog posts) had the same header (“bonney.io, by Matt Monney”). This was fine for the home page, where it made sense for the “title” to be the name of the site and the author’s name. However, it didn’t feel right on the about or projects pages – on those pages it made much more sense for the title of the page to be, well, the title of that page.

Each page on this site has a small blurb called the front matter, which are a handful of lines that tell Jekyll what the page’s layout, title, subtitle (optional), description (optional), date and external link (optional) should be. This front matter is then used to fill in various elements in the <head> tag for the static page Jekyll generates, along with – in the case of the layout tag – what user-defined page layout should be used (essentally, how various elements should be laid out on-screen).

(Please contact me and let me know if I’m getting any of this wrong – this is all to the best of my understanding.)

As an example, here is the front matter for the /about page:

---
layout: page
title: "About Me"
---

This tells Jekyll that the page should follow the layout given by a file called page.html, which in turn looks like this:

---
layout: default
---
{% include header.html %}
<div class="container">
    <div class="row">
            <div class="col-md-10 col-md-offset-1">
            {{ content }}
        </div>
    </div>
</div>
<hr>

default is yet another layout that essentially sets the basic HTML structure of the page; the details of that aren’t super important. {{ content }} is simply the content of a file called about.md, which is a Markdown file with the content of the page.

See the bit right after the front matter? {% include header.html %}? This is what header.html looked like before the changes I made this morning:

<header class="intro-header">
    <div class="container">
        <div class="row">
            <div class="col-md-10 col-md-offset-1">
                <div class="site-heading">
                    <h1>bonney.io</h1>
                    <h3>by Matt Bonney</h3>
                    <hr class="small">
                </div>
            </div>
        </div>
    </div>
</header>

Every page (again, not blog posts – those use a different layout) had this same header, with <h1>bonney.io</h1> and <h3>by Matt Bonney</h3>. Not very dynamic.

Remember those front matter tags? layout, title, subtitle, description, date and external link? You can access those values in a very similar manner as {% include header.html %}. Essentially, all you have to do to reference, say, a given page’s title tag somewhere with the page, is type {{ page.title }}.

You can similarly do this with lots of other variables about the given page – {{ page.date }}, {{ page.subtitle }}, {{ page.description }} and so on all work. So, given that I knew I wanted each page to have it’s own unique title (and optionally a description) in the header, I changed the code in header.html to look like this:

<header class="intro-header">
    <div class="container">
        <div class="row">
            <div class="col-md-10 col-md-offset-1">
                <div class="site-heading">

                    <h1>
                    {% if page.title %}
                        {{ page.title }}
                    {% else %}
                        {{ site.title }}
                    {% endif %}
                    </h1>

                    {% if page.subtitle %}
                    <h3>
                        {{ page.subtitle }}
                    </h3>
                    {% endif %}

                    {% if page.description %}
                    <span class="subheading">
                        {{ page.description }}
                    </span>
                    {% endif %}

                    <hr class="small">

                </div>
            </div>
        </div>
    </div>
</header>

Okay, that’s way more complicated, so let me break it down for you:

  • Establish the h1 tag.
  • If the page has a title tag defined in the front matter, use that title as the content of h1, otherwise, use the site’s title (a globablly-defined variable in a seperate file).
  • Check if the page has a subtitle tag; if so, add an h3 tag and fill it with the subtitle.
  • Check if the page has a description tag; if so, add a <span> with custom styling and fill it with the description.

I then made sure the front matter for my index page has the correct tags:

---
layout: page
title: "bonney.io"
description: "by Matt Bonney"
---

And did the same for about and projects, opting to give them only a title, no subtitle or description tags:

---
layout: page
title: "About Me"
---
---
layout: page
title: "Projects"
---

And that’s it. Each page now gets it’s own unique header, rather than sharing the one generic header, and it’s completely dynamic based off the front matter tags. The header onindex now looks like this:

index

While the one on projects now, appropriately looks like this:

projects

I really love this system of tags and variables, especially being able to use if-statements in the form of {% if whatever %}. The more I dig in to Jekyll, the more I’m loving it.