Jekyll Liquid Usage - Complete Template Syntax Guide
Liquid is the templating language used by Jekyll. This guide covers the essential Liquid syntax for building dynamic Jekyll sites. Liquid was created by Shopify and is one of the most widely used template languages in the Ruby ecosystem. Understanding Liquid is essential for anyone working with Jekyll, as it powers everything from simple variable output to complex page layouts.
How Liquid Works
Liquid uses two types of delimiters:
- Output tags
{{ }}: Output the value of a variable or expression - Logic tags
{% %}: Execute logic like conditionals, loops, and includes
These delimiters can be used anywhere in your Jekyll markdown or HTML files.
Reference
- https://jekyllrb.com/docs/step-by-step/02-liquid/
Tags
- https://jekyllrb.com/docs/liquid/tags/
Adding - after {% or before %} removes whitespace around the tag (e.g., {%- if ... -%}).
page variable
The whitespace control with - is particularly useful when generating HTML, as extra whitespace from Liquid tags can affect your page layout.
syntax highlight
def foo
puts 'foo'
enddef foo():
print('foo')Supported languages include ruby, python, javascript, html, css, bash, java, json, yaml, and many more. You can also add line numbers with linenos:
1
2
3
def hello
puts 'hello world'
end
Link
- Link by Tag: provides link validation on build time. if front matter not exists, the error below occurs.
- Liquid Exception: Could not find document ‘_posts/tools/jekyll/2023-12-05-jekyll-seo.md’ in tag ‘link’. Make sure the document exists and the path is correct. in /github/workspace/_posts/tools/jekyll/2023-12-04-jekyll-liquid.md
- [Link by variables] % link _posts/tools/jekyll/2023-12-05-jekyll-seo.md %: this way is not supported on Github Pages.
- Link by post_url: able to access other directory’s post with post name
The link tag is preferred over hardcoded URLs because it validates that the linked page exists at build time. If you rename or delete a post, the build will fail with a clear error message rather than silently creating a broken link.
Filter
Filters transform the output of a Liquid variable. They are applied using the pipe | character.
- Capitalize
- default value
- 29 Nov 2023
Commonly Used Filters
| Filter | Description | Example |
|---|---|---|
capitalize |
Capitalizes the first letter | {{ "hello" | capitalize }} → Hello |
downcase |
Converts to lowercase | {{ "HELLO" | downcase }} → hello |
upcase |
Converts to uppercase | {{ "hello" | upcase }} → HELLO |
strip_html |
Removes HTML tags | {{ "<p>text</p>" | strip_html }} → text |
truncate |
Truncates to N characters | {{ "long text" | truncate: 4 }} → long… |
date |
Formats a date | {{ page.date | date: "%Y-%m-%d" }} |
default |
Default value if nil/empty | {{ var | default: "N/A" }} |
jsonify |
Converts to JSON | {{ site.data.items | jsonify }} |
where |
Filters an array | {{ site.posts | where: "draft", false }} |
sort |
Sorts an array | {{ site.posts | sort: "title" }} |
if
page variable
You can also use elsif and else for more complex conditions:
{% if page.category == "tutorial" %}
This is a tutorial
{% elsif page.category == "blog" %}
This is a blog post
{% else %}
This is other content
{% endif %}
Other comparison operators include ==, !=, >, <, >=, <=, contains, and, or.
for
The for loop also supports useful features like limit, offset, and reversed:
{% for post in site.posts limit:5 %}
{{ post.title }}
{% endfor %}
{% for post in site.posts offset:2 limit:3 %}
{{ post.title }}
{% endfor %}
Inside a for loop, you can access forloop.index (1-based), forloop.index0 (0-based), forloop.first, and forloop.last to control rendering logic.
assign
You can create and set variables using assign:
{% assign my_variable = "Hello World" %}
{% assign post_count = site.posts | size %}
capture
The capture tag lets you store a block of content in a variable:
{% capture full_url %}{{ site.url }}{{ page.url }}{% endcapture %}
include
You can also pass parameters to includes:
{% include alert.html type="warning" message="Be careful!" %}
Inside alert.html, access the parameters with {{ include.type }} and {{ include.message }}.
Common Pitfalls
- Raw tag for Liquid in code blocks: When showing Liquid code examples, wrap them in raw/endraw tags to prevent Jekyll from processing them.
- Variable scope: Variables defined inside
forloops orifblocks are accessible outside them in Liquid, unlike most programming languages. - Nil checking: Use an
ifcheck or thedefaultfilter to handle nil values gracefully.
Comments