Using iteration tags in theme development is pretty much a necessity when creating a Shopify theme that will showcase multiple products (which is definitely most cases). We'll generally use the for loop to display each product from a shop or collection on the page. This is great for just placing the products on the page, but doesn't give a lot of options if you want to set up more complicated html markup and/or varying css classes.

This is where the Liquid Tag Cycle comes in. Cycle allows you to loop through a group of strings and outputs them in the order that they were passed as parameters. Each time cycle is called, the next string that was passed as a parameter is output.

To explain it's usefulness, it's worth looking at an example. If you want to make a grid of 4 products across, you may want to add an extra class to every 4th div. To do this you'd use cycle:

  
    {% for product in collection.products | limit:9 %}
      
{% endfor %}

This code will put the class left on every one. But the cycle sets it blank for the first 3 iterations and then puts 'last' on the fourth class. If there is more than 4 products it starts the iteration again.

Note that we cycle is usually used within a for loop, because it doesn't actually iterate itself, it only adds text during the iterations.

Your markup up then end up looking like this:

  
    

Advanced Cycling

But what if you want to make a more involved grid, that requires more sophisticated markup 😳 ?

You can also use cycle to create this grid:

As with the other example, we start with a for loop, looping over productions in a collection. I'm limiting the number of products to 6 because this grid looks best with multiples of 3. You could easily change this to 9 or 12 or more and you would have alternating grid patterns for as long as you have products.

This time we're grouping the cycles with 'section-group-start' and 'section-group-end'. Also, instead of creating just classes, we're creating HTML elements.

  
    {% for product in collection.products | limit:6 %}
      {% cycle 'section-group-start': '<div class="flex-grid">', '', '', '
', '', '' %} ... {% cycle 'section-group-end': '', '','
' %} {% endfor %}

Above, we create a div with a class of 'flex-grid'. We want to have 2 other divs inside this, so we add 2 blank strings. Then we have another div with a class of 'flex-grid' that we also add the class 'reverse' to. This is so that every second div will have reverse, creating that mirror image of the previous grid. We also must add two more blank strings because cycle will otherwise go right back to the first 'flex-grid' div after the 4th iteration.

We then also have to create a cycle for the ending div tag. It's the opposite of the first, so 2 blank strings, then a closing div (of course we don't need to repeat this, because both div tags close with the same thing.

Next we create more cycles to create a div that will have 1 image (our class is 'big') and a div that will have 2 images (our class is 'small')

  
    {% for product in collection.products | limit:6 %}
      {% cycle 'section-group-start': '<div class="flex-grid">', '', '', '
', '', '' %} {% cycle 'section-group-2-start': '
', '
', '' %} ... {% cycle 'section-group-2-end': '
', '', '
' %} {% cycle 'section-group-end': '', '','
' %} {% endfor %}

So again we have a div with classes 'flex-grid' and 'big' and then we have a div with a class 'flex-grid' and 'small' and then a blank string because we want 2 images to be in that div.

In the closing inner cycle we close the div, then empty string for the second image in 'samll', then close the 'small' div.

Now we've got the markup we need for this fun grid 🎉🎉

For simplicity's sake, I'm just going to add the product image in the loop, but it's likely you'll want to add at least a link to the product.

  
    {% for product in collection.products | limit:6 %}
      {% cycle 'section-group-start': '<div class="flex-grid">', '', '', '
', '', '' %} {% cycle 'section-group-2-start': '
', '
', '' %} {% cycle 'section-group-2-end': '
', '', '
' %} {% cycle 'section-group-end': '', '','
' %} {% endfor %}

The HTML will end up looking like this

  
    

Then just add the css.

  
    .flex-grid {
      display: flex;
      justify-content: center;
    }
    .small {
      flex-direction: column;
      justify-content: space-between;
    }
    .reverse {
      flex-direction: row-reverse;
    }
    img {
      margin: 10px;
    }
	

I've specifically kept this code simple to highlight the concepts. Depending on the aspect ratio of the photos, this may look a little wonky. It's likely some added css would be required to deal with this - the property object-fit might be ideal 😃.