Liquid is a template language created by Shopify. It’s available as an open source project on GitHub, and is used by many different software projects and companies.

Jekyll uses Liquid language to reuse code and add some programming logic to give ability to developers to reduce repeating code. Jekyll uses it to load data dynamically, access data across the site, implement conditional logics like if, for, case etc.,

Table of Contents

This is simplest and yet comprehensive templating language you may have ever seen or used. Look at following example

{% if age >= 18 %}
  You're allowed to vote, Yay!
{% else %}
  You are a minor! :(
{% endif %}

Simple enough, right?. Let’s dive into learning Liquid templating language further. Keep three things in mind that Liquid offers us

Tags

Liquid tags are used to define logic that tells templates what to do. Tags are wrapped with curly brace percentage delimiters {% %}

Tags are used to implement control flows, iterations etc., The best example for this would be the one I have mentioned above - legal age for voting rights.

In the example below, the if tag defines the condition to be met. If product.available returns true, then the price is displayed. Otherwise, the sold-out message is shown.

{% if product.available %}
  Price: $99.99
{% else %}
  Sorry, this product is sold out.
{% endif %}

Along with conditional statements, tags are also used for special purposes like including a file from _includes folders. Consider following example

{% include head.html %}
{% include header.html %}
{% include footer.html %}

These statements will look for the files head.html, header.html and footer.html and insert them in the places where the tags are defined. I have discussed this here as well.

Objects

Liquid objects represent variables that you can use to build your theme. Object types include store resources, standard content, and functional elements that help you to build interactivity. Object will always have an output to print

Objects, along with their properties, are wrapped in curly brace delimiters {{ }}.

Objects are used to output dynamic data on a page. In Jekyll, we have front matter title for almost all pages and posts. This can be accessed inside that page or post using the following object,

{{page.title}}

This will replace it with value assigned to title in page’s front matter

Filters

Liquid filters are used to modify Liquid output. To apply filters to an output, add the filter and any filter parameters within the output’s curly brace delimiters {{ }}, preceded by a pipe character |. A simple example is given below

{{ product.title | upcase }}

The filter upcase will turn title to all upper case text/letters

I hope by now you have a basic idea of how liquid syntax works. But these are very simple examples. There can be complex liquid code blocks as well. Let’s discuss some variables that we can use in Jekyll.

Here is a link for all the filters that you can use: Liquid Filters

Site Variables

These are sitewide objects. They can be used anywhere on the website to fetch data either something related to the site or data from _config.yml file.

VariableDescription
site.timeThe current time (when you run the jekyll command).
site.pagesA list of all Pages.
site.postsA reverse chronological list of all Posts.
site.static_filesA list of all static files (i.e. files not processed by Jekyll’s converters or the Liquid renderer). Each file has five properties: path, modified_time, name, basename and extname.
site.html_pagesA subset of site.pages listing those which end in .html.
site.html_filesA subset of site.static_files listing those which end in .html.
site.collectionsA list of all the collections (including posts).
site.dataA list containing the data loaded from the YAML files located in the _data directory.
site.documentsA list of all the documents in every collection.
site.categories.CATEGORYThe list of all Posts in category CATEGORY.
site.tags.TAGThe list of all Posts with tag TAG.
site.urlContains the url of your site as it is configured in the _config.yml.

Site variables defined in _config.yml are very useful and can be used to change things globally. Imagine you define your facebook username in the configuration file. You can access this from anywhere on the site.

Let’s say this is how you define all the social media accounts in _config.yml,

facebook: bagwanpankaj
twitter: bagwanpankaj
github: bagwanpankaj

Let’s say you create an author section with follow buttons,

Follow me on:
<a href="https://facebook.com/{{site.facebook}}" target="_blank" >
    <i class="footer-icon fa fa-facebook-official"></i>
</a>

<a href="https://twitter.com/{{site.twitter}}" target="_blank" >
    <i class="footer-icon fa fa-twitter"></i>
</a>

<a href="https://github.com/{{site.github}}" target="_blank" >
    <i class="footer-icon fa fa-github-alt"></i>
</a>

This comes in very handy if you want to use these variables very often or change them altogether. I have used this feature while creating themes. Defining accent colors in configuration helps change the color globally.

Page variables

VariableDescription
page.contentThe content of the Page, rendered or un-rendered depending upon what Liquid is being processed and what page is.
page.titleThe title of the Page.
page.excerptThe un-rendered excerpt of a document.
page.urlThe URL of the Post without the domain, but with a leading slash, e.g. /2008/12/14/my-post.html
page.dateThe Date assigned to the Post. This can be overridden in a Post’s front matter by specifying a new date/time in the format YYYY-MM-DD HH:MM:SS (assuming UTC), or YYYY-MM-DD HH:MM:SS +/-TTTT (to specify a time zone using an offset from UTC. e.g. 2008-12-14 10:30:00 +0900).
page.idAn identifier unique to a document in a Collection or a Post (useful in RSS feeds). e.g. /2008/12/14/my-post/my-collection/my-document
page.categoriesThe list of categories to which this post belongs. Categories are derived from the directory structure above the _posts directory. For example, a post at /work/code/_posts/2008-12-24-closures.md would have this field set to [‘work’, ‘code’]. These can also be specified in the front matter.
page.collectionThe label of the collection to which this document belongs. e.g. posts for a post, or puppies for a document at path _puppies/rover.md. If not part of a collection, an empty string is returned.
page.tagsThe list of tags to which this post belongs. These can be specified in the front matter.
page.dirThe path between the source directory and the file of the post or page, e.g. /pages/. This can be overridden by permalink in the front matter.
page.nameThe filename of the post or page, e.g. about.md
page.pathThe path to the raw post or page. Example usage: Linking back to the page or post’s source on GitHub. This can be overridden in the front matter.
page.nextThe next post relative to the position of the current post in site.posts. Returns nil for the last entry.
page.previousThe previous post relative to the position of the current post in site.posts. Returns nil for the first entry.

Page variables are page specific. They can only fetch data with respect to the page they are declared in.

Loops (for)

{% for post in site.posts %}
{{post.title}}
{% endfor %}

Here is the output

GIT TIP#3 Cherry pick - only pick what is needed

How stuff work Hypertext Transfer Protocol (HTTP)

GIT TIP#2 Squash merge commit instead of merge

Output above has been limited to 3, otherwise it actually prints all the post’s title. You can also fetch titles manually (not recommended!)

{{ site.posts[0].title }}
{{ site.posts[1].title }}
{{ site.posts[2].title }}
.
.
.
{{ site.posts[n].title }}

Here n should be an integer. This method is not practical. You can use it if you’re willing to fetch the titles of first few posts.

For numbering a loop, you can use forloop.index. This can also be used to provide different ids for consecutive elements in a for loop.

{% for post in site.posts %}
  {{forloop.index}}. {{post.title}}
{% endfor %}

The output would look like following:

1. GIT TIP#1 Using stash effectively

2. Learning is like rowing upstream; not to advance is to drop back

3. Layman’s guide for Cyber Security

4. Humongous: A Ruby MongoDB Browser
.
.
.
n. Nth post title

Conditionals (if/else)

{% if page.title contains 'Jekyll' %}
  This is a Jekyll related article.
{% endif %}
{% if page.title contains 'Liquid' %}
  This is a Liquid related article.
{% endif %}
{% if page.title contains 'Jekyll' and 'Liquid' %}
  This is a Jekyll Liquid article!
{% else %}
  This is neither Jekyll nor a Liquid article.
{% endif %}

Since this page has a title that contains both Jekyll and Liquid, the output is as shown above.

Else if in Jekyll Liquid Syntax is implemented this way,

{% if page.url == '/liquid/' %}
  The page URL for this page is /liquid/
{% elsif page.url == '/jekyll-liquid/' %}
  The page URL for this page is /jekyll-liquid/
{% endif %}

The output will be,

The page URL for this page is /jekyll-liquid/

This is exactly how I have implemented active menu highlight for this blog. Navigate to About or Contact page and see how the coloured-underline gets highlighted.

For loops will usually have more than one output but if conditions will have only one output.

Please go through this document to get familiar with other types of conditional flows.


About The Author

I am Pankaj Baagwan, a System Design Architect. A Computer Scientist by heart, process enthusiast, and open source author/contributor/writer. Advocates Karma. Love working with cutting edge, fascinating, open source technologies.

  • To consult Pankaj Bagwan on System Design, Cyber Security and Application Development, SEO and SMO, please reach out at me[at]bagwanpankaj[dot]com

  • For promotion/advertisement of your services and products on this blog, please reach out at me[at]bagwanpankaj[dot]com

Stay tuned <3. Signing off for RAAM