Syntax Basics
The three delimiters, output tags, filters, whitespace control, and comments.
Quill templates are HTML files with special tags mixed in. The server reads these tags, fills in your data, and sends plain HTML to the browser.
There are three types of delimiters. Each one does a different job.
Output tags
Use double curly braces to print a value:
{{ product.title }}The value is HTML-escaped by default. This means characters like <, >, and & are converted to safe HTML entities. Your templates are protected from script injection without any extra work.
To output raw, unescaped HTML, use the raw filter:
{{ product.description | raw }}Logic tags
Use curly-brace-percent tags for logic. These control what gets rendered but do not output anything on their own:
{% if product.available %}
<button>Add to Cart</button>
{% endif %}Logic tags handle conditions, loops, variables, and more. Each tag type has its own page in this section.
Filters
Filters change how a value is displayed. Add them after a value with the pipe character (|):
{{ product.title | upcase }}
<!-- Output: SILK BLOUSE -->Pass arguments to a filter with a colon:
{{ product.title | truncate: 20 }}
<!-- Output: first 20 characters -->Pass multiple arguments with commas:
{{ product.title | truncate: 20, '...' }}Chain multiple filters together. They run left to right:
{{ product.description | strip_html | truncate: 100 }}This first removes all HTML tags, then cuts the result to 100 characters.
See the Filters reference for every available filter.
Dot notation
Access nested properties with dots:
{{ product.featured_image.src }}
{{ customer.default_address.city }}Access array items by index with square brackets:
{{ product.images[0].src }}
{{ product.tags[1] }}Whitespace control
Templates can produce extra blank lines and spaces in the output. Use a hyphen (-) next to the delimiter to strip whitespace on that side:
{%- if product.available -%}
In stock
{%- endif -%}Without the hyphens, this would produce blank lines before and after "In stock". With them, the output is clean.
You can strip whitespace on one side only:
{{- product.title }} <!-- strips whitespace before -->
{{ product.title -}} <!-- strips whitespace after -->
{%- if true %} <!-- strips before only -->
{% endif -%} <!-- strips after only -->Comments
Comments are stripped from the output. Use them to leave notes for other developers:
{% comment %}
This text will not appear on the page.
Use comments to explain complex logic.
{% endcomment %}The liquid tag
When you need several lines of logic without repeating {% %} on every line, use the liquid tag:
{% liquid
assign sale = false
if product.compare_at_price > product.price
assign sale = true
endif
if sale
echo product.compare_at_price | money
endif
%}Inside a liquid block, you write one tag per line without delimiters. This keeps dense logic clean and easy to read.
echo
The echo tag outputs a value inside a liquid block. It works the same as {{ }} but follows the one-tag-per-line format:
{% liquid
assign greeting = 'Welcome'
echo greeting
echo product.title | upcase
%}Outside of a liquid block, use the normal {{ }} syntax instead.
Raw blocks
If you need to show Quill syntax without it being parsed (for example, in a code tutorial), wrap it in a raw block:
{% raw %}
{{ this will appear as literal text, not a variable }}
{% endraw %}Everything inside {% raw %} and {% endraw %} is treated as plain text.
Truthy and falsy values
Quill uses simple rules for what counts as true or false:
- Falsy:
nil(null) andfalse. Only these two values are falsy. - Truthy: Everything else, including
0, empty strings (""), and empty arrays.
This means you can check if a value exists with a simple if:
{% if product.featured_image %}
<img src="{{ product.featured_image.src }}" />
{% endif %}If featured_image is nil, the condition is false. If it has any value at all, the condition is true.