Skip to main content


<r:loop>, <r:loop:each>, <r:loop:index>, <r:item>, <r:item_count>

Repeats a block of content.

There are three types of loops that can be performed.

  1. Set number of iterations
  2. From one integer to another
  3. Over a delimited list of items

The attribute options for the loop depend on the type of loop being performed.


Set number of iterations:

<r:loop:each times="10">
  This content will be repeated 10 times.

From one integer to another:

<r:loop:each from="5" to="15">
  This content will repeat 10 times.

Over a delimited list of items:

  <r:loop:each items="first,second,third,fourth" delimiter=",">
    <li><r:item /></li>

The example above will generate the <ul> below:

  • first
  • second
  • third
  • fourth

The <r:item> tag can be used within the <r:loop:each> tag to access the value of the current item being processed by the loop. The delimiter attribute defaults to a comma.

Example using a custom page attribute for an attribute option:

The values for any of the attribute options can come from page attributes, custom page attributes, template variables, URL query parameters, or even page content regions.

<r:loop:each items="{$page_items_var}" delimiter="|">
  <p><r:item /></p>

If the page_item_var variable has been setup as a custom page attribute, and its value is 'one|two|three', then the following content would be rendered.


You can access the number of items for a loop with the <r:item_count> tag.

<r:loop items="foo,bar,baz">
<p>Item Count: <r:item_count /></p>
    <p><r:item /></p>

You can get the index of a loop like so:

  <r:loop:each items="One, Two, Three, Four">
      <a href="#">Item <r:item /> with an index of <r:index /></a>

Different from <r:item_count />, <r:index /> starts at zero and counts up. This has various programming applications. These tags must be used inside a loop.


Liquid allows you to iterate through a series of items and format them according to the markup you've specified within the r:each tag. These items can be pages, files, or blog posts.

The official Liquid documentation has several examples of iteration. You can iterate with:

  • for
  • for (with parameters)
  • cycle
  • cycle (with parameters)
  • tablerow
  • tablerow (with parameters)

View the official Shopify documentation to see examples of each type of iteration or read more about loops on our Conditional Logic & Loops page.


Iterate through an array of items:

{% assign items = "bear,bird,cow" | split: "," %}
<p>Item Count: {{ items.size }}</p>
  {% for item in items %}
    <li>{{ item }} {{ forloop.index }}</li>
  {% endfor %}

☝️ See what other options are available alongside forloop.index in the official Shopify documentation.

Iterate through blog posts:

{% assign articles = blog.articles %}
{% for article in articles.all %}
  <h2>{{ }}</h2>
{% endfor %}

Iterate through pages:

{% assign pages = site.pages %}
  {% for page in pages.all %}
      <a href="{{ page.url }}">{{ }}</a>
  {% endfor %}

Iterate through files/images for a lightbox gallery:

{% capture gallerypage %}{{ page.slug }}-gallery{% endcapture %}
{% assign images = site.files | filter_files: tags: gallerypage, types: "image" %}
  {% for image in images.all %}
    <li class="col-md-4 col-lg-3 mb-3">
      <a href="{{ image | image_url: size: "960x640" }}" title="{{ image.description }}">
        <img src="{{ image | image_url: size: "480x320" }}" alt="{{ image.alt_text }}" />
  {% endfor %}

Last updated on March 16, 2021.

We welcome all questions, feedback and bug reports. If you're having an issue, we usually need the following information:

  • A brief description of the issue
  • A link to the page where you saw the issue
  • Screenshots that illustrate the problem - How do I take a screenshot?

Kindly email for help or use the form on the request help page.