Image gallery with thumbnails

Hey it’s me again and hopefully for the last time. I want to build an image gallery like this: http://www.adhocraum.com/LB1.html There should be a large image and a thumbnail grid nearby. I don’t know how I get the large image displayed, when the user is clicking on a thumbnail. This is my template so far:

<h2><?= $page->title() ?><br><?= $page->laufzeit() ?></h2>
<div class="gallery">
  <div class="large">
    <!-- large image here -->
  </div>
  <div class="thumbs">

    <?php foreach ($page->images() as $image): ?>

        <?= $image ?>
        <!-- thumbnails here -->

    <?php endforeach ?>

  </div>
</div>

I got the page images displayed on the right side but i didn’t figured out how:

  • to add a css class in this php line
  • to crop them to have a 1:1 ratio

I tried this like in the YouTube tutorial, but it didn’t worked in this case
https://youtu.be/QwjX8JAwBws?t=2531

Thank you!

Hm, that page loads a new page when a thumbnail is clicked. I suggest you go with a JavaScript solution for this usecase instead. When a user clicks on a thumbnail, you exchange the current large image with the one from the thumbnail.

To crop the images for the thumbnails, you can use the $image->crop() method, see the docs. I currently only have a very slow internet connection, so will provide more information when it works again.

Okay I found a Javascript tutorial for a gallery with thumbnails and it worked!

<h2><?= $page->title() ?><br><?= $page->laufzeit() ?></h2>

<div class="gallery">
  <div class="large">
    <?php if($image = $page->image()): ?>
      <img id="mainImage" src="<?= $image->url() ?>" alt="">
    <?php endif ?>
  </div>
  <div class="thumbs" onclick="changeImage(event)">
    <?php foreach($page->images() as $image): ?>
      <figure>
        <img src="<?= $image->url() ?>" alt="">
      </figure>
    <?php endforeach ?>
  </div>
</div>

<script type="text/javascript">

  function changeImage(event) {
    event = event || window.event;
    var targetElement = event.target || event.srcElement;
    if (targetElement.tagName == "IMG") {
      document.getElementById("mainImage").src = targetElement.getAttribute("src");
    }
  }

</script>

My last problem now is, when I add ->crop(100) between $image and ->url() it also crops the large image. I only want to crop the tumbnails to a 1:1 ratio + I don’t want to set a pixel value. Is it possible to get a 1:1 ratio with flexible width on the thumbnails?

You would have to fetch the original image url, I’d store it in a data-src attribute, like so:

<h2><?= $page->title() ?><br><?= $page->laufzeit() ?></h2>

<div class="gallery">
  <div class="large">
    <?php if($image = $page->image()): ?>
      <img id="mainImage" src="<?= $image->url() ?>" alt="">
    <?php endif ?>
  </div>
  <div class="thumbs" onclick="changeImage(event)">
    <?php foreach($page->images() as $image): ?>
      <figure>
        <img src="<?= $image->crop(100)->url() ?>" data-src="<?= $image->crop(100)->url() ?>">
      </figure>
    <?php endforeach ?>
  </div>
</div>

<script type="text/javascript">

  function changeImage(event) {
    event = event || window.event;
    var targetElement = event.target || event.srcElement;
    if (targetElement.tagName == "IMG") {
      document.getElementById("mainImage").src = targetElement.getAttribute("data-src");
    }
  }

</script>

Okay, but the 100 is for pixel, right? I need a 1:1 thumbnail width a 100% width, because the width should not be static.

But depend on what? Thumbnails always have a given width, you can use a srcset to make them responsive, but I’m not sure I understand what you want to achieve.

Okay I made a sketch:

The pink ones are how it should be and the red ones are how it is. The photos having all a ratio of 3:2. On the overview page I always take the first image of the project and want it to display 1:1. On the exhibition page the thumbnails should also be 1:1.

So when the browser window gets sized, the thumbnails should also resize. Actually they size perfectly, but in their 3:2 ratio :man_shrugging: Here is my code for the overview page:

HTML:

<?php
// group exhibitions by year
$exhibitionGroups = $page->children()->sortBy("date","desc")->group(function($p) {
  return $p->date()->toDate('y');
});
// loop through groups
foreach($exhibitionGroups as $year => $itemsPerYear): ?>
  <div class="jahr">
    <p class="jahreszahl"><?= $year ?></p>
    <div class="shows">
       <!-- loop through items of each year group -->
      <?php foreach($itemsPerYear as $item) : ?>
        <div class="box">
        <a href="<?= $item->url() ?>">
          <?= $item->image() ?>
        </a>
        </div>
      <?php endforeach; ?>
    </div>
</div>
<hr>
<?php endforeach ?>

CSS:

.jahr {
  width: 100%;
}

.jahreszahl {
  font-size: 20px;
}

.shows {
  margin: 0 1rem 1rem 1rem;
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  grid-column-gap: 1rem;
}

.box img {
  width: 100%;
}

Because they have seven exhibitions every year, they want all seven exhibitions in a single row (desktop version). So I think the thumbnails have to be flexible. If on the exhibition page the ratio is 3:2 it might be okay at the end, but for the overview it would be much better in 1:1.

Well, you are not cropping the image but outputting it as is.

<?= $item->image()->crop(200) ?>

will give you a square of 200*200 pixels.