1

I have an unusual layout that requires formatting images 3 different ways for each 3 images. Then I need to repeat that set - if more images exist. I have a clunky way to start it now but wondered if there was a cleaner way to do it. Here's what I have so far:

{# set 1 #}

<div class="flexItem"> {% for image in entry.gallery.limit(1).all() %} <img class="unique1" src="{{ image.url }}"> {% endfor %}

<div class="flexRight"> {% for image in entry.gallery.limit(1).offset(1).all() %} <img class="unique2" src="{{ image2.url }}"> {% endfor %}

{% for image in entry.gallery.limit(1).offset(2).all() %}
&lt;img class=&quot;unique3&quot; src=&quot;{{ image3.url }}&quot;&gt;
{% endfor %}

</div> </div>

{# set 2 if more images exist #}

<div class="flexItem"> {% for image in entry.gallery.limit(1).offset(4).all() %} <img class="unique1" src="{{ image.url }}"> {% endfor %}

<div class="flexRight"> {% for image in entry.gallery.limit(1).offset(5).all() %} <img class="unique2" src="{{ image2.url }}"> {% endfor %}

{% for image in entry.gallery.limit(1).offset(6).all() %}
&lt;img class=&quot;unique3&quot; src=&quot;{{ image3.url }}&quot;&gt;
{% endfor %}

</div> </div>

Glorfindel
  • 203
  • 1
  • 3
  • 10
glider
  • 647
  • 3
  • 13

1 Answers1

2

If you only need to assign different classes, you can achieve that with the cycle function:

{% set gallery = entry.gallery.all() %}
{% set classes = ['unqiue1', 'unique2', 'unique3'] %}

{% for image in gallery %} <img class="{{ cycle(classes, loop.index0) }}" src="{{ image2.url }}"> {% endfor %}

If you also need to differentiate the output based on the loop position relative to the image triplets (first, second or third), you can use the modulus operator:

{# Position is 0, 1, or 2. #}
{% set position = loop.index0 % 3 %}

{% if position == 0 %} {# The current image is first in a triplet of images #} {% endif %}

If you need to add some final output (for example, to close any open wrapper elements), you can use loop.last to check if the current item is the last one in the list:

{% if loop.last %}
    {# Close the last row. #}
    </div>
{% %}

As a sidenote, you usually don't need to output different classes at all or wrappers at all if you use CSS grid to create your layout. You can also target every third images starting with the first using :nth-child():

.gallery__image:nth-child(3n + 1) {
    // targets very third item starting with the first one
}
MoritzLost
  • 11,215
  • 5
  • 22
  • This worked great, thank you! I had use cycle before but hadn't thought about this application.

    One final thing need is put a conditional in to test if an image exists. Right now, if an image doesn't exist the layout gets broken. I assume because the last loop doesn't fire to close the html. Tried using {% if image | length %}{% endif %} but that doesn't seem to work.

    – glider Feb 09 '23 at 14:28
  • @glider You can use loop.last to check if you're on the last item in the row, I've updated my answer with an example. If this solves your issue, please remember to mark the answer as accepted. Thanks! – MoritzLost Feb 09 '23 at 17:36