Liquid Cheat Sheet
Liquidꜛ is an open-source template language created by Shopify ꜛ in 2006. It is written in Ruby ꜛ and it is used by many ꜛ hosted web applications like Jekyll websites. Since my website is a Jekyll website, I thought that it would be very helpful to have something like a Liquid glossary at hand, just to know, how the Liquid syntax looks like and which commands are available.
Therefore I’ve created this Cheat Sheet, that gives an overview of Liquid commands one might encounter while developing a Jekyll website. It’s a conglomerate of the sources listed below. For a more complete overview, please visit, e.g., the Jekyll ꜛ or Shopify ꜛ documentation website.
The Liquid template language and its main components
Webpages can contain both static and dynamic content. Static content is content, that remains always the same on multiple pages (i.e., content won’t change just by re-visiting a page or switching to another one). Dynamic content changes from one page to the next.
A template language enables the re-use of the static elements that define the layout of a webpage, while dynamically populating the page with data from the website. The static elements are written in HTML, and the dynamic elements are written in Liquid. The Liquid elements in a file act as placeholders: When the code in the file is compiled, the placeholders are replaced by data from the website.
Acknowledgement: The information in this section was retrieved from the Shopify documentation website ꜛ. Further information on template processing can be found in this Wikipedia article ꜛ.
The Liquid syntax can be categorized into three main component types:
Liquid component | Description | Example |
---|---|---|
tag | Liquid tags contain some commands that are internally used within the Liquid template processing. | {% some commands %} |
object | Liquid objects are output on your page | {{ my_variable }} |
filter | Liquid filters change the output of a Liquid object or variable | {{ "adam!" | capitalize | prepend: "Hello " }} |
Some general commands
Command | Description | |
---|---|---|
{% comment %}Some comment.{% endcomment %} {% comment %}{% assign var = 9 %}{% endcomment %} |
Comments: skips rendering the enclosed Liquid code and text | |
{% include archive-single.html type=entries_layout %} |
Inserts rendered content of another template within the current template | |
{% highlight %} |
Enables syntax highlighting. See examples here. |
To display raw Liquid expressions, enclose them by the raw
/endraw
tag:
Variables
Command | Description | |
---|---|---|
{% assign my_variable = 5 %} |
define a variable | |
{% assign my_variable = site.my_collection | map: 'tags' | join: ',' | split: ',' | uniq %} |
defining a variable with some extra filters | |
{{ my_variable }} |
outputs a variable or object on your page | |
{% capture my_variable %}Some text{%endcapture%} My variable: {{ my_variable }}. > My variable: Some text |
captures the enclosed string (which can also be a Liquid object) and assigns it to a variable (stored as a string) |
for loops
Command | Description | |
---|---|---|
{% for tag in my_variable %} {% <h3>{{tag}}</h3> %} <ul> {% for page in site.my_collection %} {% if page.tags contains tag %} {% <li><a href="{{ site.baseurl }}{{ note.url }}">{{ note.title }}</a></li> %} {% end if %} {% endfor %} </ul> {% endfor %} |
for loop with an if condition | |
{% break %} |
stops the iteration of a loop | |
{% continue %} |
skips the iteration within a loop | |
{% for item in array limit:2 %} |
limits the loop to the specified number of iterations | |
{% for item in array offset:2 %} |
starts the loop at the specified offset index | |
{% for i in (start..stop) %} {% assign num = 4 %} {% assign my_range = (1..num) %} |
defines a range of numbers | |
{% for item in array reversed %} |
reverses the order of the loop |
Cycling
Looping through a group of strings and outputs them in the order that they were passed as arguments. On each call, the next string argument is output:
{% cycle "one", "two", "three" %}
{% cycle "one", "two", "three" %}
{% cycle "one", "two", "three" %}
cycle
with “cycle group” parameters (for multiple cycle
blocks):
{% cycle "first": "one", "two", "three" %}
{% cycle "second": "one", "two", "three" %}
{% cycle "second": "one", "two", "three" %}
{% cycle "first": "one", "two", "three" %}
If no name is supplied for the cycle group, then it is assumed that multiple calls with the same parameters are one group.
if statements
Command | Description | |
---|---|---|
{% if my_var == 5 %} my_var is 5 {% elsif my_var == 10 %} my_var is 10 {% else %} my_var is not 5 and not 9 {% endif%} |
if statement with elsif and else |
|
{% unless my_var == 9 %} my_var is still not 9 {% endunless%} |
the opposite of if (equivalent to != ) |
Boolean operators | Description | |
---|---|---|
== |
equal | |
!= |
not equal | |
> |
greater than | |
< |
less than | |
>= |
greater than or equal to | |
<= |
less than or equal to | |
or |
logical or | |
and |
logical and | |
contains |
checks for the presence of a substring inside a string | |
true |
logical true | |
false |
logical false |
Liquid maths
Command | Description and example | |
---|---|---|
divided_by |
dividing a number {% assign var = 10 %} {{ 20 | divided_by: var }} |
|
modulo |
returns the remainder of a division operation {{ 5 | modulo: 2 }} |
|
times |
multiplying a number {{ assign var2 = var | times: 1.0 }} |
|
minus |
substracting a number {{ 5 | minus: 1 }} |
|
plus |
adding a number {{ 5 | plus: 1 }} |
|
increment |
Creates and outputs a new number variable (initial value 0). On each call, it increases its value by 1 and outputs the new value. {% increment my_counter %} {% increment my_counter %} {% increment my_counter %} You can also increment predefined variables. Each call increases its value by 1 and outputs the new value: {% assign my_counter = 5 %} {% increment my_counter %} |
|
decrement |
similar to increment , but decreasing the corresponding variable by 1 {% decrement my_counter %} |
|
round |
rounds an input to the nearest integer (or to the optional passed number of decimal places) {{ 5.78 | round }} {{ 5.785 | round: 2 }} |
|
floor |
rounds an input down to the nearest whole number {{ 5.78 | floor }} |
|
ceil |
rounds an input up to the nearest whole number {{ 5.78 | ceil }} |
|
abs |
returns the absolute value of a number {{ -5 | abs }} |
|
size |
returns the number of characters/items in a string/array {{ "some string" | size }} You can use it with dot notation when you need to use the filter inside a tag: {% if site.pages.size > 10 %} |
|
number_of_words |
counts the number of words in some text (Jekyll specific) {{ "Hello world!" | number_of_words }} |
|
at_most |
limits a number to a maximum value {{ 4 | at_most: 5 }} |
|
at_least |
limits a number to a minimum value {{ 4 | at_least: 5 }} |
|
to_integer |
converts a string or boolean to integer (Jekyll specific) {{ some_var | to_integer }} |
Special filters
Filter | Description and example | |
---|---|---|
downcase |
transforms each character in a string lowercase {{ "Men from Mars" | downcase }} > men from mars |
|
upcase |
transforms each character in a string uppercase {{ "Men from Mars" | upcase }} > MEN FROM MARS |
|
capitalize |
transforms each character in a string capitalized and converts the remaining characters to lowercase {{ "Men from Mars" | capitalize }} > Men from mars |
|
truncatewords |
Shortens a string down to the number of words passed as an argument. If the specified number of words is less than the number of words in the string, an ellipsis (…) or custom ellipsis (e.g., -- ) is appended to the string. {{ "One two three four." | truncatewords: 3 }} > One two three... {{ "One two three four." | truncatewords: 3, "--" }} > One two three-- {{ "One two three four." | truncatewords: 3, "" }} > One two three |
|
truncate |
Shortens a string down to the number of cahracters passed as an argument. If the specified number of characters is less than the length of the string in the string, an ellipsis (…) or custom ellipsis (e.g., , and so on ) is appended to the string and is included in the character count. {{ "One two three four." | truncate: 10 }} > One two... {{ "One two three four." | truncate: 18, ", and so on" }} > One two, and so on {{ "One two three four." | truncate: 7, "" }} > One two |
|
slice |
Returns a substring of one character or series of array items beginning at the index specified by the first argument. An optional second argument specifies the length of the substring or number of array items to be returned. String or array indices are numbered starting from 0. {{ "Water" | slice: 0 }} > W {{ "Water" | slice: 3 }} > e {{ "Water" | slice: 2,4 }} > ter |
|
strip |
removes all whitespace (tabs, spaces, and newlines) from both the left and right sides of a string (does not affect spaces between words) !{{ " This is some text " | strip }}. > !This is some text. |
|
rstrip |
removes all whitespace from both the right side of a string !{{ " This is some text " | rstrip }}. > ! This is some text. |
|
lstrip |
removes all whitespace from both the left side of a string !{{ " This is some text " | lstrip }}. > !This is some text . |
|
strip_newlines |
removes newline characters from a string {{ string | strip_newlines }} |
|
newline_to_br |
inserts an HTML line break (<br /> ) in front of each newline (\n ) in a string {{ string | newline_to_br }} |
|
compact |
removes any nil ꜛ values from an array Example. ꜛ |
|
strip_html |
removes any HTML tags from a string {{ "This <em>is</em> some <strong>text</strong>." | strip_html }} > This is some text. |
|
url_encode |
converts URL-unsafe characters in a string into percent-encoded characters {{ "john@liquid.com" | url_encode }} > john%40liquid.com |
|
url_decode |
decodes a string that has been encoded as a URL or by url_encode {{ "Hey%21" | url_decode }} > Hey! |
|
split |
divides a string into an array using the argument as a separator {% assign var = "One, two, three, four" | split: ", " %} {{ var }} > One two thre four |
|
replace |
replaces every occurrence of the first argument in a string with the second argument {{ "Take my car and bring it to my home" | replace: "my", "your" }} > Take your car and bring it to your home |
|
replace_first |
replaces only the first occurrence of the first argument in a string with the second argument {{ "Take my car and bring it to my home" | replace_first: "my", "your" }} > Take your car and bring it to my home |
|
append |
appends a string (can also be a variable) to another string ``{% raw %}{{ “/my_url” |
append: “.html” }}<br> > /my_url.html` |
prepend |
adds the specified string to the beginning of another string {{ "apples, oranges and bananas" | prepend: "Some fruit: " }} > Some fruit: apples, oranges and bananas |
|
concat |
concatenates multiple arrays {% assign fruits = "apples, oranges, peaches" | split: ", " %} {% assign vegetables = "carrots, turnips, potatoes" | split: ", " %} {% assign all = fruits | concat: vegetables %} {{ all }} > apples oranges peaches carrots turnips potatoes |
|
remove |
removes every occurrence of the specified substring from a string {{ "I strained to see the train through the rain" | remove: "rain" }} > I sted to see the t through the |
|
remove_first |
removes only the first occurrence of the specified substring from a string {{ "I strained to see the train through the rain" | remove_first: "rain" }} > I sted to see the train through the rain |
|
join |
combines the items in an array into a single string using the argument as a separator {% assign array = "add, Zack, Orpheus, Albert, Stephen, snake" | split: ", " %} {{ array | join: ", " }} > add and Zack and Orpheus and Albert and Stephen and snake |
|
map |
creates an array of values by extracting the values of a named property from another object {% assign all_categories = site.pages | map: "category" %} |
|
where |
creates an array including only objects with a given property value (or any true value by default) {% assign tag_postcards = tags | where: "type", "postcard" %} |
|
uniq |
removes any duplicate items in an array {{ my_array | uniq | join: ", " }} |
|
sort |
sorts items in an array in case-sensitive order {% assign array = "add, Zack, Orpheus, Albert, Stephen, snake" | split: ", " %} {{ array | sort | join: ", " }} > Albert, Orpheus, Stephen, Zack, add, snake |
|
sort_natural |
sorts items in an array in case-insensitive order {% assign array = "Zack, Orpheus, Albert, Stephen" | split: ", " %} {{ array | sort_natural | join: ", " }} > Albert, Orpheus, Stephen, Zack |
|
first |
returns the first item of an array {{ "One two three four" | split: " " | first }} > One {% assign var = "One, two, three, four" | split: ", " %} {{ var.first }} > One |
|
last |
returns the last item of an array {{ "One two three four" | split: " " | last }} > four {% assign var = "One, two, three, four" | split: ", " %} {{ var.last }} > four |
Dates
The date
filter converts a given timestamp into another date format. The format for this syntax follows the guidelines of strftime. E.g.,
{{ post.date | date: "%a, %b %d, %y" }}
Thur, Aug 17, 21
{{ post.date | date: "%Y" }}
2021
{{ "May 4, 2020" | date: "%a, %b %d, %y" }}
Thur, May 4, 20
You can also work with the current time and date:
{{ "now" | date: "%Y-%m-%d %H:%M" }}
2021-08-11 20:15
Info: now
returns the current time and date each time when your Jekyll website is built. You can use this, e.g., for implementing an automatic “This website/page was updated on …” information on your website or page.
The following date filters are Jekyll specific ones:
Command | output |
---|---|
{{ site.time | date_to_xmlschema }} |
2008-11-07T13:07:54-08:00 |
{{ site.time | date_to_rfc822 }} |
Mon, 07 Nov 2008 13:07:54 -0800 |
{{ site.time | date_to_string }} |
07 Nov 2008 |
{{ site.time | date_to_string: "ordinal", "US" }} |
Nov 7th, 2008 |
{{ site.time | date_to_long_string }} |
07 November 2008 |
{{ site.time | date_to_long_string: "ordinal" }} |
7th November 2008 |
Jekyll specific filters
The following filters are special Jekyll filters:
Filter | Description and example | |
---|---|---|
where |
Selects all objects in an array where the key has the given value. {{ site.members | where:"graduation_year","2014" }} |
|
where_exp |
Selects all objects in an array where the expression is true. {{ site.members | where_exp:"item", "item.graduation_year == 2014" }} {{ site.members | where_exp:"item", "item.graduation_year < 2014" }} {{ site.members | where_exp:"item", "item.projects contains 'foo'" }} |
|
find |
Returns the first object in an array for which the queried attribute has the given value or return nil if no item in the array satisfies the given criteria. {{ site.members | find: "graduation_year", "2014" }} |
|
find_exp |
Returns the first object in an array for which the given expression evaluates to true or return nil if no item in the array satisfies the evaluated expression. {{ site.members | find_exp:"item", "item.graduation_year == 2014" }} |
|
group_by |
Groups an array’s items by a given property. {{ site.members | group_by:"graduation_year" }} |
|
group_by_exp |
Groups an array’s items using a Liquid expression. {{ site.members | group_by_exp: "item", "item.graduation_year | truncate: 3, ''" }} |
|
array_to_sentence_string |
Converts an array into a sentence (e.g. useful for listing tags). Optional argument for connector. {{ page.tags | array_to_sentence_string }} |
|
markdownify |
Converts a Markdown-formatted string into HTML. {{ page.excerpt | markdownify }} |
|
smartify |
Converts “quotes” into smart quotes. {{ page.title | smartify }} |
|
slugify |
Converts a string into a lowercase URL slug. {{ "The _config.yml file" | slugify }} > the-config-yml-file slugify accepts the following extra filter options, each specifying what to filter: none (no characters) raw (spaces) default (spaces and non-alphanumeric characters) pretty (spaces and non-alphanumeric characters except for ._~!$&'()+,;=@ ) ascii (spaces, non-alphanumeric, and non-ASCII characters) latin (like default, except Latin characters are first transliterated) |
|
normalize_whitespace |
Replaces any occurrence of whitespace with a single space. {{ "a \n b" | normalize_whitespace }} |
Jekyll’s link tag
Linking with Jekyll’s link
tag ꜛ ensures valid URLs of your Jekyll pages (posts, pages, collection items, files) even if the permalink style to include them changes (or gets deactivated). The file extension must be included in the link
tag declaration as well as its relative path starting from the root directory, e.g.,
{% link _posts/2016-07-26-name-of-post.md %}
There is an extra tag for linking to posts: The post_url
tag will generate the correct permalink URL for the post you specify, so you can leave the preceding _posts/
. Also, you don’t have to append the file extension. E.g.:
{% post_url 2010-07-21-name-of-post %}
Note, that if you organize your posts in subdirectories, you need to include the subdirectory path to the post (e.g., {% post_url /subdir/2010-07-21-name-of-post %}
).
Advantage: The major benefit of link
and post_url
tags is link validation: If the link doesn’t exist, Jekyll won’t build your site and you are alerted to a broken link, that you can then fix.
Be aware: What you can’t do with link
and post_url
tags, is adding filters to the link
tags. E.g., you can’t {% link mypage.html | append: "#section1" %}
(- )to link to sections on a page, use regular HTML or Markdown linking techniques).
Jekyll’s site and page variables
The following variables are global variables recognized by your Jekyll website:
Global variable | Description | |
---|---|---|
site |
Access to site wide information and configuration settings from _config.yml . |
|
page |
Access to page specific information and settings from its front matter. Also custom variables set via the front matter will be available from this variable. |
Site variables
Variable | Description |
---|---|
site.time |
The current time (when you run the jekyllcommand). |
site.pages |
A list of all pages. |
site.posts |
A reverse chronological list of all posts. |
site.related_posts |
If the page being processed is a post, this contains a list of up to ten related posts. By default, these are the ten most recent posts. For high quality but slow to compute results, run the jekyll command with the –lsi (latent semantic indexing) option (works not on GitHub Pages) |
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 . For example, if you set url: http://mysite.com in your configuration file, then it will be accessible in Liquid as site.url (leave off trailing forward slashes, i.e., do: url: http://mysite.com , don’t http://mysite.com/ ). For the development environment, there is an exception: If you are running jekyll serve in a development environment, site.url will be set to the value of host , port , and SSL-related options. This defaults to url: http://localhost:4000 |
site.baseurl |
Name of the sub-directory the site is served from. It’s not needed for most sites and can be omitted (only necessary when hosting your site in a sub-directory, e.g., as project sites ꜛ on GitHub). |
site.[CONFIGURATION_DATA] |
All the variables set via the command line and your _config.yml are available through the site variable. For example, if you have foo: bar in your configuration file, then it will be accessible in Liquid as site.foo . Jekyll does not parse changes to _config.yml in watch mode, you must restart Jekyll to see changes to variables. |
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). |
page.categories |
The list of categories to which the 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. |
When to use the {{page.baseurl}} tag
Linking to files in your main GitHub page:
When you are running a main website as a GitHub user page ꜛ (<username>.github.io
), no extra URL tag is necessary to define links:
Markdown:
[about page](/about.html)
HTML:
<a href="/about.html">about page</a>
Linking to a file on GitHub project pages:
When you serve your website from a subdirectory (e.g., as a project page ꜛ on GitHub, say, /project_A
), you need to define this subdirectory in the site.baseurl
variable in the _config.yml
(leave off trailing forward slashes, e.g., do: baseurl: /project_A
, don’t: baseurl: /project_A/
). All relative links (which are generally the most commonly used links) then have to be defined as follows:
Markdown:
[about page](/project_A/about.html)
[about page]({{ site.baseurl }}/about.html)
[about page]({{ '/about.html' | relative_url }})
HTML:
<a href="/project_A/about.html">about page</a>
<a href="{{ site.baseurl }}/about.html">about page</a>
<a href="{{ '/about.html' | relative_url }}">about page</a>
If you link to resources that require the full URL, use:
Markdown:
[about page](http://mysite.com/project_A/about.html)
[about page]({{ site.url }}{{ site.baseurl }}/about.html)
[about page]({{ '/about.html' | absolute_url }})
HTML:
<a href="http://mysite.com/project_A/about.html">about page</a>
<a href="{{ site.url }}{{ site.baseurl }}/about.html">about page</a>
<a href="{{ '/about.html' | absolute_url }}">about page</a>
References
- Jekyll documentation on Liquid Filters ꜛ
- Jekyll documentation on Tags Filter ꜛ
- Jekyll documentation on Variables ꜛ
- Shopify documentation ꜛ
- Shopify cheat sheet ꜛ
- Shopify’s definition of a template language ꜛ
- Wikipedia article on template processors ꜛ
- Mademistakes post on Jekyll’s
site.url
andbaseurl
ꜛ
Comments
Commenting on this post is currently disabled.
Comments on this website are based on a Mastodon-powered comment system. Learn more about it here.