0

I need to make an uneven gallery, where the user can upload an infinite number of images. The gallery is composed of a pattern of 7 images that is repeated indefinitely.

The website mainly uses Paragraphs, so I created a Paragraph Gallery, where the user can directly upload the media. I set up three image styles: small, tall, and big.

I also prepared a simple CodePen with the style solution. But now I’m struggling with the Twig template. I tried some solutions from previous discussions, but they either failed or didn’t generate the images.

{% block content %}
  {% for image in content.field_images['#items'] %}
    {% if image %}

  <div class="gallery">
    <div class="gallery-left">
      <div class="inner-wrapper">
        <div class="inner-left">
          {% if loop.first %}
          <div class="field__item">
            <img src="{{ image|file_uri|image_style('tall') }}" alt="{{ image.alt }}">
          </div>
          {% endif %}
          {% if loop.index == 2 %}
            <div class="field__item">
              <img src="{{ image|file_uri|image_style('small') }}" alt="{{ image.alt }}">
            </div>
          {% endif %}
        </div>
        <div class="inner-right">
          {% if loop.index == 3 %}
            <div class="field__item">
              <img src="{{ image|file_uri|image_style('tall') }}" alt="{{ image.alt }}">
            </div>
          {% endif %}
          {% if loop.index == 4 %}
            <div class="field__item">
              <img src="{{ image|file_uri|image_style('small') }}" alt="{{ image.alt }}">
            </div>
          {% endif %}
        </div>
      </div>
    </div>
    <div class="gallery-right">
      {% if loop.index == 5 %}
        <div class="field__item">
          <img src="{{ image|file_uri|image_style('small') }}" alt="{{ image.alt }}">
        </div>
      {% endif %}
      {% if loop.index == 6 %}
        <div class="field__item">
          <img src="{{ image|file_uri|image_style('tall') }}" alt="{{ image.alt }}">
        </div>
      {% endif %}
    </div>
    <div class="bottom">
      {% if loop.index % 7 == 0 or loop.last %}
        <div class="field__item">
          <img src="{{ image|file_uri|image_style('big') }}" alt="{{ image.alt }}">
        </div>
      {% endif %}
    </div>
  </div>
{% endif %}
  {% endfor %}
{% endblock %}
DarkBee
  • 16,592
  • 6
  • 46
  • 58
Tita
  • 3
  • 1
  • 2
  • Shouldn't your `{% for %}`- loop be *inside* `
    `? Now you are creating a full gallery div for each of the images
    – DarkBee Oct 05 '21 at 07:51
  • That makes a lot more sense, @DarkBee, thanks! After the {% for %} loops were tucked inside the
    elements, the images in the initial block were displayed correctly. But the block pattern still didn't get repeated. It just glued the last uploaded image to the bottom of the initial block.
    – Tita Oct 06 '21 at 07:19

2 Answers2

0

Try something along the lines of the below, I have used the batch and splice filters to break up the image array into blocks and then conditional checks to determine the appropriate image size.

{% block content %}

    {% for gallery_block in content.field_images['#items']|batch(7) %}

        <div class="gallery">

            <div class="gallery-left">
                <div class="inner-wrapper">
                    <div class="inner-left">
                        {% for image in gallery_block|slice(0,3) %}
                            {% if image %}
                                <div class="field__item">
                                    {% set size = ( loop.index is even ) ? 'small' : 'tall' %}
                                    <img src="{{ image|file_uri|image_style(size) }}" alt="{{ image.alt }}">
                                </div>  
                            {% endif %}
                        {% endfor %}
                    </div>
                </div>
            </div>

            <div class="gallery-right">
                {% for image in gallery_block|slice(4,5) %}
                    {% if image %}
                        <div class="field__item">
                            {% set size = image.first ? 'small' : 'tall' %}
                            <img src="{{ image|file_uri|image_style(size) }}" alt="{{ image.alt }}">
                        </div>
                    {% endif %}
                {% endfor %}
            <div>

            {% set bottom_image = gallery_block|last %}
            {% if bottom_image %}
                <div class="bottom">    
                    <div class="field__item">
                        <img src="{{ bottom_image|file_uri|image_style('big') }}" alt="{{ bottom_image.alt }}">
                    </div>
                </div>
            {% endif %}

        </div>

    {% endfor %}

{% endblock %}
WPhil
  • 1,056
  • 1
  • 7
  • 12
  • Thank you for this idea @WPhil. I tested the batch idea before and it crashed the site each time. With your solution the html elements get generated, but the images don’t. – Tita Oct 06 '21 at 07:12
  • Verify the paths of the images in the generated source – DarkBee Oct 06 '21 at 07:28
  • also you can use {{ dump( image ) }} to check the contents of the image variable – WPhil Oct 06 '21 at 10:24
0

Based on @WPhil's idea with batch I would do it like it is proposed below.

Things to note:

  • Image uri can be retrieved from file entity and not from media nor field reference list item this is why content.field_images['#items'].0 is not enaugh and it should be something like content.field_images['#items'].0.entity.field_media_image.entity
  • batch filter has three arguments and within loops like this is important to reset the index so this is why the third arggument is FALSE

Gallery paragraph file

{% import "_impression_image.html.twig" as impression %}

{% block content %}

  {% for impressions_gallery_batch in content.field_images['#items']|batch(7, NULL, FALSE) %}

    {# Define all image file entities for given batch of image items #}
    {% set image_entities = {} %}
    {% for impressions_gallery_batch_item in impressions_gallery_batch %}
      {% set image_entities = image_entities|merge([
    impressions_gallery_batch["#{loop.index0}"].entity.field_media_image.entity,
  ]) %}
    {% endfor %}

    <div class="impressions-gallery">

      <div class="impressions-left">
        <div class="inner-wrapper">

          {% if image_entities.0 %}
            <div class="inner-left">
              {{ impression.image(image_entities.0, 'impressions_small') }}
              {{ impression.image(image_entities.1, 'impressions_tall') }}
            </div>
          {% endif %}

          {% if image_entities.2 %}
            <div class="inner-right">
              {{ impression.image(image_entities.2, 'impressions_small') }}
              {{ impression.image(image_entities.3, 'impressions_tall') }}
            </div>
          {% endif %}

        </div>
      </div>

      {% if image_entities.4 %}
        <div class="impressions-right">
          {{ impression.image(image_entities.4, 'impressions_tall') }}
          {{ impression.image(image_entities.5, 'impressions_small') }}
        </div>
      {% endif %}

      {% if image_entities.6 %}
        <div class="impressions-bottom">
          {{ impression.image(image_entities.6, 'impressions_big') }}
        </div>
      {% endif %}
    </div>
  {% endfor %}

{% endblock %}

Image item macro function (_impression_image.html.twig)

{% macro image(image_entity_item, image_style) %}
  {% if image_entity_item %}
    <div class="field__item">
      <img src="{{ image_entity_item.uri.value|image_style(image_style) }}" alt="{{ image_entity_item.alt }}">
  </div>
  {% endif %}
{% endmacro %}
zanvidmar
  • 361
  • 4
  • 13