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.
Variable | Description |
---|---|
site.time | The current time (when you run the jekyll command). |
site.pages | A list of all Pages. |
site.posts | A reverse chronological list of all Posts. |
site.static_files | A 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_pages | A subset of site.pages listing those which end in .html. |
site.html_files | A subset of site.static_files listing those which end in .html. |
site.collections | A list of all the collections (including posts). |
site.data | A list containing the data loaded from the YAML files located in the _data directory. |
site.documents | A list of all the documents in every collection. |
site.categories.CATEGORY | The list of all Posts in category CATEGORY. |
site.tags.TAG | The list of all Posts with tag TAG. |
site.url | Contains 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
Variable | Description |
---|---|
page.content | The content of the Page, rendered or un-rendered depending upon what Liquid is being processed and what page is. |
page.title | The title of the Page. |
page.excerpt | The un-rendered excerpt of a document. |
page.url | The URL of the Post without the domain, but with a leading slash, e.g. /2008/12/14/my-post.html |
page.date | The 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.id | An 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.categories | The 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.collection | The 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.tags | The list of tags to which this post belongs. These can be specified in the front matter. |
page.dir | The 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.name | The filename of the post or page, e.g. about.md |
page.path | The 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.next | The next post relative to the position of the current post in site.posts . Returns nil for the last entry. |
page.previous | The 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