January 17, 2017

> Jekyll In Style

quick 'n easy tutorial


Feeling in the mood for a change, I recently moved my website to Jekyll. This change wasn’t about the look and feel, but purely about leveraging the simplicity of the Jekyll framework. The appearance of the site had to remain absolutely identical.

Let’s say the information on how to style Jekyll sites is out there, but it’s a bit scattered. So here is my version of a step-by-step guide:

1) get rid of the default theme

Open the _config.yml of your Jekyll site (at the root of the project). You should see that the default theme is set to ‘minima’.

theme: minima

Delete the theme line and get rid of any predefined styling.

2) create your own layouts

If you now try to serve the site (jekyll serve), you will notice that, amongst others, Jekyll is complaining that it cannot find the ‘post’ layout. To remedy to this, create a _layouts directory at the root of the project.

Then define a default layout. In the _layouts folder, create a default.html file, which will describe your default layout, and add a {{ content }} tag to make sure any nested content will be included.

A typical default.html layout file could look like this:

<!DOCTYPE html>
<html lang="en">
   <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    <title>{{ page.title | escape }}</title>
  </head>

  <body>
    {{ content }}
  </body>
</html>

After that, we have to implement our more specific layouts. As Jekyll offers the possibility to nest layouts, we can specify a parent layout in the front matter and then only take care of the layout of the content block we declared in default.html.

Here is a simplistic post.html layout:

---
layout: default
---
<h1>I'm a Post:</h1>
<h2>{{ page.title }}</h2>

{{ content }}

<p>Thanks for reading me!</p>

And a home.html layout (for our index page):

---
layout: default
---
<h1>Introducing:</h1>
<h2>{{ site.title }}</h2>

<ul>
    {% for post in site.posts %}
        <li><a href="{{ post.url | relative_url }}">{{post.title}}</a></li>
    {% endfor %}
</ul>

<p><a href="/about.html">Read more</a> about this site!</p>

We won’t implement an ‘about’ layout here, so you should replace the more specific ‘page’ layout used in about.md by our generic ‘default’ layout. (Alternately, you can create your own ‘page’ layout just like we did for ‘post’.)

---
layout: default
title: About
permalink: /about/
---

If you now try to run jekyll serve, you’ll observe that the server is still complaining about a missing ‘include’. We will talk about those files in the next subsection.

3) keep it DRY

Your ‘includes’ are those files you may want to extract from your pages and layouts to make your code cleaner and more modular. They should be placed inside an _includes folder. So go ahead and create that folder at the root of your project.

Let’s open a new file called stupid-snippet.html in the _includes directory:

<p>I'm a bit stupid, but at least I'm here!</p>

At the moment, the server is trying to retrieve includes that don’t exist anymore (they were part of the ‘minima’ theme). To fix this, open the about.md page and change the text to remove the default includes (and text) and use use our own content:

We are busy making a new layout and styling it...
{% include stupid-snipped.html %}

You should now be able to serve (and view!) your Jekyll project. Woohoo!

3) add your own CSS

At this point you might feel a bit cheated. The layout we created so far doesn’t look much like an improvement! What we want to do is be able to create and apply our own stylesheets to the website. To get started with this, create not one, but two directories at the root of the project: _sass and assets.

The _sass directory is conceived to contain… your sass stylesheets. Let’s create a typography.scss file:

body {
    font-family: Futura, "Trebuchet MS", Arial, sans-serif;
    color: #dedede;
    background: #735959;

    a { color: #fff; }
}

And a layout.scss file:

body { margin: 10%; }

Now that we have those files defined, we can create a main.scss in the assets directory (as files in _sass are only available for import). This main.scss file will be compiled into main.css by Jekyll, which we will be able to load into your layouts.

This is how assets/main.scss could look like:

---
# Only the main Sass file needs front matter (the dashes are enough)
---
@charset "utf-8";

@import "typography";
@import "layout";

… Which we load into default.html:

<link rel="stylesheet" href="{{ '/assets/styles/shared.css' | relative_url }}">

Of course then you are absolutely free to add classes to your layouts in order to style your content even more! (You can also drop html into your Markdown files, whenever you need that extra bit of customisation.)

4) load page-specific CSS

It is generally recommended to load all the CSS in the head of the page in order to prevent a flash of unstyled content. However, in a nested template structure such as ours, the head is defined in the topmost template (here: layout.html).

Problem: we want to load page- or layout-specific CSS without having to redefine a base layout every time. Solution: use a front matter css value and parse it to build the head of layout.html.

Here is how we give this capability to the head of layout.html:

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no">
    <link rel="stylesheet" href="/assets/main.css">
    <title>{{ page.title | escape }}</title>

    {% for css in layout.css %}
        <link rel="stylesheet" type="text/css" href="/assets/" />
    {% endfor %}

    {% for css in page.css %}
        <link rel="stylesheet" type="text/css" href="/assets/" />
    {% endfor %}
</head>

Let’s put this into use by adding a blue-bg.css file into the assets directory:

body { background: #29183e; }

… Which we can now for instance load into about.md. To do so, we simply need to update the front matter of the file:

---
layout: default
title: About
permalink: /about/
css: blue-bg.css
---

This will load our custom stylesheet in about.md and turn the background of the page blue. (By the way, the technique would also work for includes or Javascript files!)


And… voilà! It’s now up to you to get cracking and create your own fabulously unique Jekyll site.

I tend to find static tutorials difficult to follow, so I created a small GitHub repo where you can go through history and follow the steps commit after commit. Go have a look.

In the meantime, happy coding :)