Dev Notes

Software Development Resources by David Egan.

Page Sections in Jekyll - Seperating Content from Layout


Jekyll, Liquid
David Egan

It’s usually considered good practice to keep content separate from logic and layout. I think this is especially important with static site generators like Jekyll, where it’s easy to mix content and layout.

Achieving separation is pretty straightforward with single page/post/collection views - just define a custom template and inject the content from a markdown file (from yaml frontmatter and the main content field).

But what about displaying section content in a single page context? This is a common requirement for landing pages, home pages and single page sites.

Ideally, all content - including text, background image, foreground image etc should be controlled in the content markdown file. I’d go a step further and suggest that some style elements should also be controllable here - for example, if you add a background image which results in poor text/background contrast, you should be able to set the image overlay opacity in the same location that you’re setting the image.

Define Collections

Jekyll collections are an ideal candidate for managing repeating content that is not naturally date ordered.

Our use case here is for a very simple site, and our section content will be grouped using a jekyll collection that we’ll call “sections”.

To begin, define the site collections in _config.yml:

collections:
- sections

Then create a directory called _sections in the project root. This directory will contain section files, stored in markdown format.

The Index Page

Iterating through the sections in index.html looks like this:

{% assign sections = site.sections | sort: 'order' %}
{% for section in sections %}
  {% if section.include != null %}
    {% include {{ section.include }} %}
  {% else %}
    {% include sections/default.html %}
  {% endif %}
{% endfor %}

This does the following:

  1. Assign a ‘sections’ object, by iterating through site sections (i.e. the _sections/*.md files) and ordering by the “order” attribute (which is set in the section front matter)
  2. Loop through these objects - for each one, if there is a specified include (again, set in the section frontmatter) then call it
  3. If no include is specified in the section, call a default include as a fallback

The Includes

In our case we store includes under _includes/sections.

The includes are html files that have the section content injected. This include shows how:

  • Inline style is included as defined by the section yaml frontmatter
  • Section content is injected into the section layout
{% capture bg-image-style %}
 style="background:{% if section.bg-opaque-overlay != nil %} linear-gradient(
    {{ section.bg-opaque-overlay }},
    {{ section.bg-opaque-overlay }}
  ),{% endif %} {% if section.bg_image != nil %}url('{{ section.bg_image }}') center center fixed; background-size: cover;{% endif %}"
{% endcapture %}
<section id="{{ section.title | slugify }}" class="content-section"{{ bg-image-style }}>
  <div class="row">
    <div class="col-md-12">
      <h1>{{ section.title }}</h1>
      {{ section.content }}
    </div>
  </div>
</section>

In this case the style rule builds in a background image with an opaque overlay.

Obviously you can define as many layout includes as your project needs.

The Content

Content is held as a collection markdown file stored in the /_sections directory.

For example, this is _sections/about.md:

---
title: About
image: path/to/img
# Set the display order for this section
order: 3
# Specify the layout for this section
include: sections/two-column.html
# Set style variables
bg-opaque-overlay: rgba(0,200,0,0.3)
bg_image: http://loremflickr.com/2000/600/robot
---
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.

### Ut enim ad minim veniam

quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.

Duis aute irure dolor in reprehenderit in voluptate velit...

I like this method because content editing on the site is very simple, and site editors can have quite a few options available in the content markdown file. It also breaks apart the layout/HTML which I think makes projects more maintainable.

There are probably better ways of organising section content - if you know of any, please leave a comment!

References


comments powered by Disqus