Skip to content
Log in

Render - Liquid Tag Reference

On this page

The render simple tag renders a template file inline and explicitly passes variables to it. Unlike the older include tag, render isolates variable scope: only the variables you pass are available inside the rendered template, so the partial is self-contained and reusable without side effects.

Syntax

```liquid

{% render “snippets/product-card”, product: product %} ```

```liquid

{% render “components/form”, action: “checkout”, title: “Review Order”, readonly: false %} ```

Property Value
Tag Name render
Type Simple tag
Source Hydrofoil (core)

How it works

When you render a template, you pass data as named parameters. Those parameters become local variables inside the rendered template. The rendered template cannot see:

  • The caller’s assign variables
  • The caller’s loop variables (from for blocks)
  • The caller’s capture blocks

But the rendered template can always see:

  • Global Liquid variables like current_store, current_customer, current_cart
  • Any global objects injected by the controller
  • Standard Liquid filters and tags

This isolation makes partials safe to reuse in different contexts without accidentally breaking their behavior.

Parameters and locals

The rendered template receives parameters as locals (local variables available only inside that template). You can pass any Liquid value: strings, numbers, booleans, arrays, objects, and template variables.

```liquid

{% render “checkout/order-summary”, order: current_order, show_shipping: true, items_label: “Items in order” %} ```

Inside the rendered template, those are available as order, show_shipping, and items_label.

Default parameters in snippets

Use the default tag at the top of a rendered snippet to set fallback values for optional parameters:

```liquid

{% render “card”, title: “Default Title”, subtitle: page.description %} ```

In the snippet:

```liquid

{%- default title: “Untitled” -%} {%- default subtitle: “” -%}

{{ title }}

{%- if subtitle %}<p>{{ subtitle }}</p>{%- endif -%} ```

When a parameter is not passed, it takes its default value. When it is passed, the default is overridden.

Composition and recursive rendering

Rendered templates can themselves render other templates, building larger components from smaller ones. This composition pattern is the foundation for reusable theme architecture:

```liquid

{%- render “card-container” -%} {%- render “card”, heading: “Feature One” -%} {%- render “card”, heading: “Feature Two” -%} {%- endrender -%} ```

Rendered templates can also render themselves recursively, useful for tree structures like category hierarchies or nested menus. Pass an array of items and loop over it, rendering the template for each item:

```liquid

{%- for item in items -%} {%- render “tree-node”, node: item, level: level | plus: 1 -%} {%- endfor -%} ```

When to use render

Use render when you want:

  • Self-contained partials — pass exactly the data each partial needs, nothing more
  • Reusable snippets — the same template can be used in different contexts without interference
  • Safe composition — build complex pages by nesting rendered templates
  • Testable code — each partial’s behavior depends only on its parameters

Execution context

The render tag runs at template-render time, before the page is sent to the browser. Parameters are passed synchronously, and the rendered output appears inline.

Examples

Render a product card

Pass the product and a title override:

```liquid

{%- for product in collection.products -%} {%- render “products/card”, product: product, show_price: true -%} {%- endfor -%} ```

In snippets/products/card.liquid:

```liquid

{%- default show_price: false -%}

{{ product.name }}

{%- if show_price %} {{ product.pricing.price | money }} {%- endif -%} View

```

Render a sidebar with multiple sections

Compose a sidebar from separate section renderers:

```liquid

```

Each renderer in snippets/sidebar/ is isolated and receives only the parameters it needs.

Render a reusable form snippet

Create a form renderer that works across multiple pages:

```liquid

{%- render “forms/text-input”, label: “Email Address”, name: “email”, placeholder: “you@example.com”, required: true -%}

{%- render “forms/text-input”, label: “Phone”, name: “phone”, placeholder: “(555) 000-0000” -%} ```

In snippets/forms/text-input.liquid:

```liquid

{%- default required: false -%}

<input type="text" id="{{ name }}" name="{{ name }}" placeholder="{{ placeholder }}" {%- if required %} required{%- endif -%} >

```

The same form renderer works everywhere because it only depends on its parameters.

Was this article helpful?

Was this article helpful?