Tags
Los tags son la lógica del template: {% if %}, {% for %},{% render %}. Los de la plataforma están marcados conMerge.
Todos aceptan el control de espacios de Liquid: {%- y -%} sacan los espacios y saltos de línea de alrededor. include no está disponible: usárender.
Tags del theme
sectionMerge
{% section 'nombre' %}
Renderiza una sección estática (la misma en todas las páginas), típicamente el encabezado y el pie desde el layout. Sus settings se guardan en config/settings_data.json y se editan en el editor de temas. Una sección no puede incluirse a sí misma y el anidamiento tiene un tope.
{% section 'header' %}
<main>{{ content_for_layout }}</main>
{% section 'footer' %}render
{% render 'snippet', variable: valor %}
Renderiza un snippet de snippets/ con su propio alcance: solo ve las variables que le pasás y los objetos globales. Acepta for y with.
{% for product in collection.products %}
{% render 'product-card', product: product %}
{% endfor %}formMerge
{% form 'tipo', objeto, atributo: valor %} … {% endform %}
Arma un <form method="post"> con los campos ocultos que la tienda necesita. Tipos que procesa la tienda: product (agrega al carrito), contact (consulta) y customer (suscripción al newsletter). Adentro, form.posted_successfully? y form.errors tienen el resultado del último envío de ese tipo. Otros tipos de Shopify salen con action="#" y el atributo data-form-unsupported para que el theme decida qué mostrar.
{% form 'contact', id: 'contacto' %}
{% if form.posted_successfully? %}
<p>{{ 'contact.success' | t }}</p>
{% endif %}
{{ form.errors | default_errors }}
<input type="email" name="contact[email]" required>
<textarea name="contact[body]"></textarea>
<button>Enviar</button>
{% endform %}paginateMerge
{% paginate lista by cantidad %} … {% endpaginate %}
Marca el bloque paginado. La tienda ya pagina las colecciones, la búsqueda y los blogs con un tamaño de página propio (el by se acepta por compatibilidad); adentro, el objeto paginate tiene las páginas y los links.
{% paginate collection.products by 24 %}
{% for product in collection.products %}…{% endfor %}
{% if paginate.next %}<a href="{{ paginate.next.url }}">Siguiente</a>{% endif %}
{% endpaginate %}stylesheetMerge
{% stylesheet %} … {% endstylesheet %}
CSS de una sección o snippet. La plataforma junta todos los bloques en un único archivo que se carga desde content_for_header. Adentro no se interpreta Liquid.
{% stylesheet %}
.banner { padding: 4rem 1rem; }
{% endstylesheet %}javascriptMerge
{% javascript %} … {% endjavascript %}
JavaScript de una sección o snippet. Se junta en un único archivo (con defer); cada bloque corre aislado, así que el error de una sección no frena a las demás. Adentro no se interpreta Liquid.
{% javascript %}
document.querySelectorAll('[data-acordeon]').forEach((el) => { /* … */ });
{% endjavascript %}Control de flujo
if
{% if condición %} … {% elsif otra %} … {% else %} … {% endif %}
Condicional. Operadores: ==, !=, >, <, >=, <=, contains, and, or.
{% if product.available %}
<button>Agregar</button>
{% else %}
<p>Agotado</p>
{% endif %}unless
{% unless condición %} … {% endunless %}
Lo contrario de if.
{% unless product.available %}<span>Agotado</span>{% endunless %}case
{% case valor %}{% when a, b %} … {% else %} … {% endcase %}
Elige un bloque según el valor.
{% case section.settings.alineacion %}
{% when 'centro' %}<div class="centro">
{% else %}<div>
{% endcase %}Iteración
for
{% for x in lista limit: n offset: n reversed %} … {% else %} … {% endfor %}
Recorre una lista o un rango ((1..4)). El else se muestra si la lista está vacía. Adentro, forloop tiene index, first, last y length.
{% for product in collection.products limit: 4 %}
{% render 'product-card', product: product %}
{% else %}
<p>{{ 'collections.empty' | t }}</p>
{% endfor %}break
{% break %}
Termina el for.
{% for v in product.variants %}{% if v.available %}{{ v.title }}{% break %}{% endif %}{% endfor %}continue
{% continue %}
Pasa a la siguiente vuelta del for.
{% for v in product.variants %}{% unless v.available %}{% continue %}{% endunless %}{{ v.title }}{% endfor %}cycle
{% cycle 'a', 'b' %}
Alterna valores en cada vuelta.
<li class="{% cycle 'par', 'impar' %}">tablerow
{% tablerow x in lista cols: n %} … {% endtablerow %}
Filas y celdas de una tabla HTML.
<table>{% tablerow p in collection.products cols: 3 %}{{ p.title }}{% endtablerow %}</table>Variables
captureMerge
{% capture nombre %} … {% endcapture %}
Guarda en una variable lo que renderiza el bloque. Como lo capturado ya es HTML escapado por el motor, al imprimirlo no se vuelve a escapar.
{% capture titulo %}{{ product.title }} · {{ shop.name }}{% endcapture %}
<title>{{ titulo }}</title>assign
{% assign nombre = valor %}
Crea una variable.
{% assign en_oferta = product.compare_at_price > product.price %}increment
{% increment contador %}
Imprime un contador y le suma uno.
{% increment visto %}decrement
{% decrement contador %}
Le resta uno a un contador y lo imprime.
{% decrement restantes %}echo
{% echo valor | filtro %}
Imprime un valor, como {{ }}. Útil dentro de {% liquid %}.
{% liquid
echo product.title | upcase
%}Sintaxis
liquid
{% liquid … %}
Varios tags seguidos sin delimitadores, uno por línea.
{%- liquid
if variant
assign price = variant.price
else
assign price = product.price
endif
-%}comment
{% comment %} … {% endcomment %}
Comentario: no se renderiza.
{% comment %}Tarjeta de producto para grillas{% endcomment %}#
{% # comentario %}
Comentario de una línea.
{% # Precio con descuento %}raw
{% raw %} … {% endraw %}
Muestra el contenido sin interpretar Liquid (por ejemplo, plantillas de JavaScript).
{% raw %}{{ esto no se interpreta }}{% endraw %}