Liquid Tutorial

Liquid Variables

Source: Coding with Robby

Creating Variables with assign

Variables let you store intermediate values and keep templates readable. The {% assign %} tag creates a variable in the current scope. Liquid variables are dynamically typed — you do not declare types.

Allowed value types: strings, numbers, booleans, nil, arrays, and Liquid drops (Shopify objects). You cannot assign complex Ruby objects or execute functions with assign — only expressions.

assign for reusable strings and flags
{% assign greeting = "Hello" %}
{% assign on_sale = false %}
{% assign max_items = 4 %}

{% if customer %}
  <p>{{ greeting }}, {{ customer.first_name }}!</p>
{% else %}
  <p>{{ greeting }}, guest!</p>
{% endif %}

capture — Store Rendered HTML

The {% capture %} tag executes everything inside it (including other Liquid tags and HTML), captures the resulting string, and stores it in a variable. This is essential for building HTML fragments you output in multiple places or pass to snippets.

Capture conditional HTML into a variable
{% capture sale_badge %}
  {% if product.compare_at_price > product.price %}
    <span class="badge badge--sale">
      Save {{ product.compare_at_price | minus: product.price | money }}
    </span>
  {% endif %}
{% endcapture %}

{{ sale_badge }}

Without capture, you would duplicate the if block everywhere you need the badge. Capture runs the inner template once and stores the result — including an empty string if the condition is false.

increment and decrement

These tags create a counter variable in the parent scope, starting at 0. Each call to {% increment var %} returns the current value then adds 1. Useful for zebra-striping rows without manual index math.

Auto-incrementing row class
{% for item in cart.items %}
  <tr class="row-{% increment row_counter %}">
    <td>{{ item.product.title }}</td>
  </tr>
{% endfor %}
Note: assign creates or overwrites variables. increment/decrement only work with numeric counters and persist across the template render within the same scope.