Iteration
Looping with for, forloop variables, else, limit, offset, reversed, cycle, and tablerow.
Iteration tags let you run a block of code once for each item in an array. Use them to render lists of products, images, menu items, or any repeated content.
for
The main loop tag. Repeat a block for each item in an array:
{% for product in collection.products %}
<div class="product-card">
<h3>{{ product.title }}</h3>
<p>{{ product.price | money }}</p>
</div>
{% endfor %}forloop variables
Inside a for loop, you can access details about the current iteration:
| Variable | Type | Description |
|---|---|---|
forloop.index | Number | Current position, starting at 1 |
forloop.index0 | Number | Current position, starting at 0 |
forloop.first | Boolean | true on the first item |
forloop.last | Boolean | true on the last item |
forloop.length | Number | Total number of items |
forloop.rindex | Number | Position from the end, starting at 1 |
forloop.rindex0 | Number | Position from the end, starting at 0 |
{% for product in collection.products %}
<div class="product-card {% if forloop.first %}first{% endif %}">
<span class="count">{{ forloop.index }} of {{ forloop.length }}</span>
<h3>{{ product.title }}</h3>
</div>
{% endfor %}else (empty collections)
Show a fallback when the array is empty:
{% for product in collection.products %}
<div class="product-card">
<h3>{{ product.title }}</h3>
</div>
{% else %}
<p>No products found in this collection.</p>
{% endfor %}The else block only runs when the array has zero items.
limit
Restrict the loop to a set number of items:
{% for product in collection.products limit: 4 %}
<div class="product-card">
<h3>{{ product.title }}</h3>
</div>
{% endfor %}This renders only the first 4 products, even if the collection has more.
offset
Skip a number of items before starting the loop:
{% for product in collection.products offset: 2 %}
<h3>{{ product.title }}</h3>
{% endfor %}This skips the first 2 products and starts from the third.
Combine limit and offset to paginate through a list:
<!-- First 4 products -->
{% for product in collection.products limit: 4 %}
<h3>{{ product.title }}</h3>
{% endfor %}
<!-- Next 4 products -->
{% for product in collection.products limit: 4 offset: 4 %}
<h3>{{ product.title }}</h3>
{% endfor %}reversed
Loop through items in reverse order:
{% for product in collection.products reversed %}
<h3>{{ product.title }}</h3>
{% endfor %}You can combine reversed with limit:
{% for product in collection.products reversed limit: 3 %}
<h3>{{ product.title }}</h3>
{% endfor %}Looping over a range
Loop over a range of numbers:
{% for i in (1..5) %}
<span>{{ i }}</span>
{% endfor %}
<!-- Output: 1 2 3 4 5 -->Ranges are useful for generating numbered lists or repeating a block a set number of times.
cycle
Alternate between values on each loop iteration. This is useful for applying alternating CSS classes:
{% for product in collection.products %}
<div class="{% cycle 'odd', 'even' %}">
<h3>{{ product.title }}</h3>
</div>
{% endfor %}The first item gets odd, the second gets even, the third gets odd, and so on.
You can cycle through any number of values:
{% for product in collection.products %}
<div class="{% cycle 'col-1', 'col-2', 'col-3' %}">
<h3>{{ product.title }}</h3>
</div>
{% endfor %}tablerow
Generate HTML table rows automatically:
<table>
{% tablerow product in collection.products cols: 3 %}
{{ product.title }}
{% endtablerow %}
</table>This creates <tr> and <td> elements for you. The cols parameter sets how many columns each row has. After every 3 items, a new row starts.
tablerow supports the same limit, offset, and range options as for:
<table>
{% tablerow product in collection.products cols: 2 limit: 6 %}
{{ product.title }}
{% endtablerow %}
</table>break
Stop a loop early when a condition is met:
{% for product in collection.products %}
{% if product.title == 'Secret Item' %}
{% break %}
{% endif %}
<h3>{{ product.title }}</h3>
{% endfor %}When Quill hits break, it stops the loop and moves on to whatever comes after endfor. Any items left in the array are skipped.
continue
Skip the current item and jump to the next one:
{% for product in collection.products %}
{% if product.available == false %}
{% continue %}
{% endif %}
<h3>{{ product.title }}</h3>
{% endfor %}This renders every product except the ones that are not available. The loop keeps going through the rest of the array.
Nested loops
You can nest loops inside each other. Each loop has its own forloop variable:
{% for collection in collections %}
<h2>{{ collection.title }}</h2>
{% for product in collection.products %}
<p>{{ product.title }} ({{ forloop.index }} of {{ forloop.length }})</p>
{% endfor %}
{% endfor %}The inner forloop refers to the inner loop. To access the outer loop's variables, use forloop.parentloop:
{% for collection in collections %}
{% for product in collection.products %}
<p>Collection {{ forloop.parentloop.index }}, Product {{ forloop.index }}</p>
{% endfor %}
{% endfor %}