Jekyll is a great static site tool. If you’re using GitHub Pages, it comes with it for free, making it a very useful tool for any public blog or website. It comes, though, with one common problem that I’ve yet to come across a good solution for: relative paths.

The problem

<!-- _layouts/default.html -->
<link href='assets/style.css' rel='stylesheet'>

The mess of relative paths

Let’s say you have an innocent URL in your layout like the one above. This is a relative path, not an absolute one that begins with /. It resolves based on wherever it’s included from.

This works well in pages of your site placed in the root directory. Once you path one level deep though, you’ll encounter problems.

From this page… Base Final URL  
/index.html / /assets/style.css Good ✓
/me.html / /assets/style.css Good ✓
/about/profile.html /about /about/assets/style.css Wrong ✗


A naive workaround

One workaround is to use absolute paths by adding a / in the beginning.

<link href='/assets/style.css' rel='stylesheet'>
            ^

Why absolute URLs suck

This works great for sites that live on its own domain. When your site will be hosted in a sub-directory (such as the case with GitHub Project Pages), this absolute path will not resolve to /project/assets/style.css as you probably would have intended.

If your site is in… It resolves to…  
user.github.io/ /assets/style.css Good ✓
user.github.io/project/ /assets/style.css Wrong ✗


A better workaround

This snippet below automatically determines the relative base and stores it in the variable base. Place it in your partials path, and include the partial in your layouts.

<!-- _includes/base.html -->
{% assign base = '' %}
{% assign depth = page.url | split: '/' | size | minus: 1 %}
{% if    depth <= 1 %}{% assign base = '.' %}
{% elsif depth == 2 %}{% assign base = '..' %}
{% elsif depth == 3 %}{% assign base = '../..' %}
{% elsif depth == 4 %}{% assign base = '../../..' %}{% endif %}

Use it as a prefix

You can then use it as a prefix to URLs, like the examples below. You don’t need to include it all the time—just include it once in your layouts and it will be available everywhere.

{% include base.html %}
<link href='{{base}}/assets/style.css' rel='stylesheet'>
<a href='{{ base }}'>Back to home</a>
<a href='{{ base }}/about.html'>About me</a>
<a href='{{ base }}{{ post.url }}'>Read "{{ post.title }}"</a>