Liquid is a flexible and powerful templating language that powers many modern web applications and content management systems, such as Shopify, Jekyll, and Power Pages. It allows developers to create dynamic, data-driven web content without the need for complex server-side logic. Whether you’re a beginner or an experienced developer, understanding the core principles of Liquid templates is essential for creating responsive and dynamic websites. In this article, we will explore the basics of Liquid templating and provide advanced tips to help you harness its full potential.
What is Liquid?
Liquid is an open-source, Ruby-based template language created by Shopify. It is designed to separate content from the logic of the web page, enabling designers to work independently from developers. In simple terms, Liquid allows you to generate dynamic content in a web page by embedding logic and data directly into HTML.
Liquid templates are commonly used in e-commerce, blogging, and other content-driven websites. The templates include variables, loops, conditions, filters, and more, allowing developers to build dynamic and reusable components efficiently.
Key Concepts of Liquid Templates
To understand Liquid templates, it’s important to know some basic components. These include objects, tags, and filters, which combine to allow dynamic content rendering.
1. Objects
In Liquid, objects are placeholders that represent dynamic content. They are enclosed in double curly braces {{ }}
. Objects pull data from the backend system (such as a product catalog or user profile) and display it on the webpage.
Example:
<p>Welcome, {{ user.name }}!</p>
In this example, {{ user.name }}
is an object that will display the name of the user dynamically. The object could be pulled from a database or defined elsewhere in the template.
2. Tags
Tags are the logic statements in Liquid that control the flow of the template. They are enclosed in {% %}
and allow you to perform operations like loops, conditionals, and more.
Example:
{% if user.logged_in %}
<p>Welcome back, {{ user.name }}!</p>
{% else %}
<p>Please log in to continue.</p>
{% endif %}
In this example, {% if %}
is a conditional tag that checks whether the user is logged in, and the content inside the block changes accordingly.
3. Filters
Filters modify the output of objects or variables. They can be applied to objects inside the {{ }}
to change how they are displayed. Filters are written with a pipe |
symbol.
Example:
<p>{{ product.price | money }}</p>
In this example, the money
filter formats the product’s price to be displayed in the correct currency format.
Liquid Template Syntax
Liquid syntax is simple and easy to understand, with a few core components that allow you to build dynamic and reusable templates. Below is an overview of common syntax elements used in Liquid templates:
1. Variables
Variables are used to store dynamic values that can be displayed on the page. They are defined using the {% assign %}
tag.
Example:
{% assign greeting = "Hello, world!" %}
<p>{{ greeting }}</p>
In this example, the variable greeting
is assigned a value, which is then output inside the <p>
tag.
2. Conditionals
Conditionals help create logic-based output. They are implemented using {% if %}
, {% elsif %}
, and {% else %}
tags.
Example:
{% if product.available %}
<p>This product is available.</p>
{% else %}
<p>This product is out of stock.</p>
{% endif %}
This condition checks if a product is available and displays different messages based on the availability.
3. Loops
Loops in Liquid are created using the {% for %}
tag, which is useful when you want to iterate over an array or list.
Example:
{% for product in products %}
<p>{{ product.name }}: {{ product.price }}</p>
{% endfor %}
This loop iterates through the products
array and displays the name and price of each product in the list.
4. Filters
As mentioned earlier, filters modify the output of objects. They are used to format or manipulate data for display.
Example:
<p>{{ user.join_date | date: "%B %d, %Y" }}</p>
In this case, the date
filter formats the join_date
of the user into a more readable format, such as “April 20, 2025”.
Advanced Liquid Template Tips
Once you’re comfortable with the basics of Liquid, you can start leveraging more advanced techniques to optimize your templates and create more complex logic. Below are some advanced tips and tricks for working with Liquid.
1. Working with Nested Loops
You can use nested loops to display data in more complex structures. For example, if you have a list of products categorized by type, you can use nested loops to display the categories and the products within them.
Example:
{% for category in categories %}
<h2>{{ category.name }}</h2>
<ul>
{% for product in category.products %}
<li>{{ product.name }}: {{ product.price | money }}</li>
{% endfor %}
</ul>
{% endfor %}
This code will loop through all categories, and for each category, it will display a list of its products with their names and prices.
2. Handling Undefined Variables
Liquid automatically outputs an empty string for undefined variables, but you can control how undefined values are handled by using the default
filter.
Example:
<p>{{ user.nickname | default: "Guest" }}</p>
If the user.nickname
is undefined, the code will display “Guest” instead of an empty string.
3. Using Arrays and Hashes
You can work with arrays and hashes (associative arrays) in Liquid to structure data and create more complex outputs.
Example (Array):
{% assign fruits = "apple,banana,orange" | split: "," %}
<ul>
{% for fruit in fruits %}
<li>{{ fruit }}</li>
{% endfor %}
</ul>
This code splits a comma-separated string into an array and loops through it to display each item.
Example (Hash):
{% assign product_info = { "name": "Laptop", "price": 999, "availability": true } %}
<p>{{ product_info.name }} - ${{ product_info.price }}</p>
This example creates a hash with key-value pairs and outputs specific values from the hash.
4. Using capture
to Store Dynamic Content
The capture
tag allows you to store a block of content in a variable for later use. This is especially useful when you need to perform logic before rendering the content.
Example:
{% capture product_info %}
<h2>{{ product.name }}</h2>
<p>{{ product.description }}</p>
{% endcapture %}
<div class="product-summary">
{{ product_info }}
</div>
Here, the capture
tag stores HTML content in a variable, which is then inserted into the page when needed.
5. Creating Reusable Includes
Liquid allows you to include external templates within your main template. This is useful for creating reusable components such as headers, footers, and product cards.
Example:
{% include 'header' %}
{% include 'footer' %}
This method is useful for maintaining consistency across multiple pages and reducing redundancy in your templates.
6. Working with Filters and Multiple Parameters
Many filters support multiple parameters, allowing you to format and manipulate data in various ways. For example, the date
filter accepts different date formats, and the money
filter accepts multiple parameters for formatting.
Example:
<p>{{ product.price | money: "$", "USD" }}</p>
In this example, the money
filter formats the price with a dollar sign and ensures that the currency is displayed in US dollars.
7. Debugging Liquid Code
Liquid provides a useful tool for debugging templates: the {{ debug }}
tag. This can be used to output the entire object or array in a readable format.
Example:
{{ product | debug }}
This will print out the product object in a human-readable format, which is helpful for identifying issues with data or logic.