I don’t have a lot of experience building sites using Jekyll. This is actually the first site I’ve built. So when I wanted to build a photo gallery, I had to try a couple of different ways of doing it to see what worked best (or you can skip straight to the code).

First, I tried using a Data File. This is, I suppose, Jekyll’s version of a database table. These files are stored in a root level folder called _data and can be written in a few different formats like CSV, JSON, and YAML. Since I’m new to Jekyll, and also to keep it consistent with other parts of Jekyll I opted to use YAML, calling it photos.yml. In this file, I used properties to hold values such as the location of both the thumbnail and full size photos, when and where I took the photo; the place name, and the latitude and longitude. I also included some Exif data, which includes the camera settings, so things such as aperture, shutter speed, ISO, focal length, white balance, etc.

The data contained in Data Files can be accessed by using the variable site.data.photos (the variable has the same name as the Data File). So I looped through each record I had in the Data File and output the thumbnail of the photos in a grid.

Using a Data File doesn’t generate any other pages, so for each photograph I would have to create a hidden container, which would show the full sized image and more information about the photo when the thumbnail was clicked.

This method had some drawbacks. So far, I’ve managed to avoid any dependencies on JavaScript. I don’t think I’ve actually written any. A first for me. The code for this site is clean and simple, so I didn’t want to add the complexity of dynamically hiding and showing photo information. This would also mean that I would have to tinker around with HTML History API so that I wouldn’t break the browser navigation.

Secondly, because this method doesn’t generate any HTML pages for the photos, it would make it much more difficult (but not impossible) to create URLs that navigate directly to a photo. I don’t know much about SEO, but I imagine that any optimisation would be much more difficult when all photos are on one HTML document.

Thirdly - scalability. This method may work fine when I’ve only got a gallery of a couple dozen photographs, but what would happen if I had hundreds or more? How would pagination work? How would it affect page performance?

I decided to look into other options and found something called Collections. These work a lot like Posts, but can be configured to include their own unique properties. By specifying a name for your collection in the Jekyll configuration (the _config.yml file) and creating a folder where you can add your documents, Jekyll will automatically generate pages for your site.

The config file (_config.yml)

collections:
  photos:
    output: true

defaults:
  - scope:
      path: ""
        type: photos
    values:
      layout: photo

Creating a collection in Jekyll is really easy, the first step is to make some small additions in the _config.yml configuration file. You define a new collection by using a key/value pair with collections: as the key and the name of the collection as the value.

In this instance I want Jekyll to create public-facing pages for my site. To render the documents in this collection into independent files, we use the optional metadata for this collection. The key/value pair of output: true achieves this.

Defaults for key/values can also be specified in the configuration file. When I create a file for a photo in my gallery, I will always want to use a layout that I created for displaying photos. So instead of specifically telling each photo page to use the photo layout, I can tell Jekyll to use the photo layout for every document I create in this collection. This saves me from having to write this bit of YAML every time I create a new photo page, and if I want to change the name of the layout or use a new layout entirely, I only have to do it in one place! Awesome.

Next, you need to create a folder to store all the documents for your collection. The folder should be created in the root and should match the name you gave to your collection and start with an underscore. As my collection is called photos, I created a folder called _photos.

A photo page (E.g. _photos/hverarond.markdown)

---
title: "Hverarönd"
datePosted: 2016-04-30 14:16:00 +0000
image: "hverarond.jpg"
exif:
  camera: "Nikon D3100"
  dateTaken: 2013-06-12 12:08 -0300
  location:
    name: "Norðurland eystra, Iceland"
---

Before building up the photo gallery and the photo pages, it’s a good idea to create a couple of markdown documents in the _photos folder so that you can test out the page layout.

The code for the photo pages is mostly a YAML data structure (within the document’s front-matter) for the photo. It includes the location of the image files to display, and various other bits of information about the photo that someone might be interested in. For the first version of my photo gallery, I’m just going to display the image, and where and when it was taken and for some, a short description underneath.

Below the front-matter is the content of the page. Most of the page is generated from the YAML within the front-matter so for me, the content would generally be a description/story of the photo (written in markdown), which can be optional.

<ul>
  {% assign sorted_photos = site.photos | sort: 'rating', 'last' %}
  {% for photo in sorted_photos %}
    <li>
      <a href="{{ photo.url | prepend: site.baseurl }}">
        <img src="assets/images/photographs/thumbs/{{ photo.image.thumbnail }}" alt="{{ photo.title }}" />
      </a>
    </li>
  {% endfor %}
</ul>

After adding a few photos, I could start putting the HTML layout together by looping through the collection. Collections are available via the site variable and collection name, so in this instance site.photos. The value of this is an array and you can access the attributes that’s the front matter of each document in the array by iterating through them in a loop.

A challenge of putting together a photo gallery is ordering the photographs in a way that looks good. This normally isn’t a logical ordering like a date order, or alphabetically. It is easy enough to define a key/value pair (such as order: 7 for example) in the front matter of each Photo page and use that as a sort order, but maintaining that ordering would be a nightmare. Trying to slot a photo in somewhere in the middle would mean that I’d have to manually increment the ordering in each Photo that appeared after it. I decided that instead of using an order key/value pair, I could use a rating key/value pair, where I could specify a number of 1 to 5 and sort it in a descending order so that my favourite photos would always be near the top.

The photo page template (_layout/photo.html)

---
layout: default
---
<div class="container">

  <figure class="photo">
    <img src="{{ page.image.original }}" alt="{{ page.title }}" />
    <figcaption>This photo was taken {% if page.exif.dateTaken %}on {{ page.exif.dateTaken | date: "%-d %B %Y" }}{% endif %} {% if page.exif.location.name %}in {{ page.exif.location.name }}{% endif %}</figcaption>
  </figure>

  {{ content }}

</div>

Ordering of photos

The layout of the Photo page will be different to blog posts and will need its own template. The layout of the Photo page is created as a HTML document in the _layout folder. Each Photo page in the photos collection will use the photo layout (I set this as a default in the _config.yml Jekyll configuration file). The photo template above uses the default layout, which includes the standard page layout like the header and footer. This means that all the layouts are separated nicely and makes things easier to maintain and change.

Pagination

I had plans to include pagination on my photo gallery (and I will have to at some point very soon), but the jekyll-paginate plugin does not support pagination on collections! There are other solutions such as the Octopress Paginate plugin but unfortunately, GitHub Pages does not support it. Since my site is hosted for free on GitHub Pages, and I don’t want to lose the deep integration of Jekyll and the awesome build process (publish with a single push to the repo) this plugin was not an option for me.

I will have to find some solution to this in the very near future, as the more photos I add, the more HTTP requests the page will need to do to download more thumbnails, and the slower the page will get and more data that the user will need to download to view the gallery. For now, there is only a handful of photos, and the thumbnails are very small, being less than 50kb each, but I want to keep improving this page, so I’m planning on putting a new version together pretty soon. :-)