Random masonry with links to subpages


I have two sections in my Kirby 3 project, ‘projects’ and ‘work’, both containing subpages. I would like to output all images of the two subpages in random order. So far, so good:

<?php $masonry = page('projects','work')->children()->listed()->shuffle(); ?>

<?php foreach($masonry->images()->shuffle() as $item): ?>
    <?php $thumb = $item->resize(480); ?>
    <a href="#linktoproject">
        <img src="<?= $thumb->url() ?>" title="<?= $item->title() ?>" />
<?php endforeach ?>

Disclaimer: I want to generate a masonry containing all images in random order. When clicking on an image, you get to a slider containing the images of the individual subpage only.

My questions:

  1. How do I link back to the actual subpage within the foreach loop (#linktoproject)?

  2. Is it possible to provide each image with a unique ID, so I can jump to the specific position in the slider? If so, what would be the most elegant soltion?

Many thanks in advance!

You can get the parent like this:

<?= $item->parent()->url() ?>

Apart from that, I’d get all the images in one go:

$masonry = page('projects','work')->children()->listed()->images()->shuffle();
foreach($masonry as $item):
// rest of code

No need to get the pages first, shuffle them, then get the image, shuffle them again…

Thank you @texnixe! I was not aware of the parent() method, that’s brilliant!

In the long run, it pays off to study all the cool methods in the docs once in a while, e.g. the file methods, just saying…

The reference is a treasure of useful stuff…

Yes, true – so much good stuff to discover :slight_smile:

Regarding my second question – I am still trying to get the link to the specific image / position in a slider (e.g. project-a/slider:3).

My approach with

$masonry = page('projects')->children()->images()->shuffle();

<?php foreach($masonry as $item): ?>

<a href="project-a/slide:<?= $item->parent()->indexOf() ?>">
  <img src="<?= $image->url() ?>" />

<?php endforeach ?>

does not do the job, as indexOf() relates to the complete shuffeled collection, instead of the parent (subpage) of the image.

How can I get an indexOf() that relates to the parent, not the whole shuffled collection?

If I get your right, you want to get the position of an image within its siblings of the same page, right? That would then be:


The important thing to note is that indexOf() is a collection method, so you can’t call it on a single item like the parent page. Instead, you pass the single item, whose position within the collection you want to get, as parameter to the method.

Thank you, that’s a pointer in the right direction. However, I think it’s slightly trickier – my setup is

Overview Page: displaying all images (thumbs) of all subpages & their children, shuffled.


Now, I would like to be able to click on a thumb in the overview section, and get directed to the specific image in the slider:


I’ve tried your suggestion <?= $item->parent()->images()->indexOf($item); ?> but with every re-load of the overview page (which is shuffled), theindexOf(); changes. Hence, I can not jump to the specific position in the slider.

I don’t see why it should change, because the index position of each image in relation to the parent page should always be the same, no matter how much you shuffle your images on the overview page. Or do you shuffle the images in the subpages as well?

This code

<a href="project-a/slide:<?= $item->parent()->indexOf() ?>">
  <img src="<?= $image->url() ?>" />

is not correct, anyway. First of all, hardcoding project-adoesn’t make sense, and $image should be $item.

Sorry, I just simplified my code for the sake of readability. This is my overview.php controller:

return function($page) {
  $masonry =  page('projects','freework','commercial')
  return [
    'masonry'  => $masonry

The relevant bit in my overview.php template:

<?php foreach($masonry as $item): ?>
  <?php $thumb = $item->resize(480); ?>

  <?php $proportion = ($item->height() / $item->width()) * 100; ?>
  <p><?php echo $item->parent()->images()->indexOf($item); ?></p>

    <a href="<?= $item->parent()->url() ?>/slide:<?= $item->parent()->images()->indexOf($item); ?>">
    <figure style="padding-bottom:<?= $proportion ?>%">
        <img class="lazy" data-src="<?= $thumb->url() ?>" title="<?= $item->parent()->title() ?>" />
<?php endforeach ?>

Whenever I reload, the numbers called with indexOf(); change. It’s also beyond my understanding why.

That’s mysterious…

My bad. I called the item indexOf(); in the masonry with

<?= $item->parent()->images()->indexOf($item); ?>">

but the images in the slider are custom sorted:

<?php foreach($page->images()->sortBy('sort', 'asc') as $image): ?>

so that was why the links seemed to go random. Adding sortBy to the masonry item

<?= $item->parent()->images()->sortBy('sort', 'asc')->indexOf($item); ?>

fixed the “mystery”. Thanks again for your help @texnixe!