Confusion over images in Kirby?

Just Googling adding images to pages in Kirby brings up lots of people asking the same questions and everyone a different answer.

I am totally confused about adding images to pages and the examples on YouTube etc all focus around galleries and not single images.

For example I’m setting up a page with a main cover image and 3 sub images, I want them all to be different file selectors in the blueprint so the client knows exactly what image they are choosing.

With all text elements it is easy to define them in the blueprint with a name and pull them through to the templates:

<?= $page->text()->kirbytext() ?>
<?= $page->text2()->kirbytext() ?>
<?= $page->text3()->kirbytext() ?>

But I’m stuck about how to do this with images? In the blueprint have a field for cover image and upload that, then have separate fields for image one etc…

Then once you have set for example the cover image, how can this be accessed from another page on a news page for example where the cover is the child’s main image?

In Kirby there are several ways to upload images: files section, files field, textarea upload, blocks upload.

For your use case, you would probably have one upload section that shows all uploaded images, and files fields to select individual images out of the uploaded ones for the cover etc.

Files sections: Files section | Kirby CMS
Files fields: Files | Kirby CMS

Whether or not the user can upload/select one or multiple images can be set through the min and max properties. You can find how to output images from a files field in the linked documentation, depending on whether the field has one or multiple images/files.

Sorry I’m still confused, Ive created a single input and added 2 files.

images:
    type: files

Added 2 files which can be seen in the backend:

I can access the first one using:

$image = $page->images()->sortBy('sort', 'asc')->first();
<img src="<?= $image->resize(1600,1600)->url() ?>" srcset="<?= $image->srcset() ?>" alt="<?= $image->alt() ?>">

But if I try to get a second it doesn’t work.

$image2 = $page->images()->sortBy('sort', 'asc')->nth(2);
<img src="<?= $image2->resize(1600,1600)->url() ?>" srcset="<?= $image2->srcset() ?>" alt="<?= $image2->alt() ?>">

The documentation for images just references getting the first image or an image by name, but what if the client has uploaded an image into the list and needs to get it?

https://getkirby.com/docs/reference/objects/cms/page/image

Sorry my confusion is coming from using other CMS’ for example in Perch CMS on my template page I only need to add:

<img src="<perch:content id="logo" type="image" label="Logo">" alt="<perch:content id="logoalt" type="text" label="Alt text">">

This creates an input in the backend that I can select an image, upload it and put it into that place on the my html page.

In Kirby CMS I don’t understand the how to reference a particular image and get it in the exact place I want in on the page.

First of all it is important to understand the difference between files section and files fields.

If you want to get a particular image only, a files field is probably the best option. It is basically a select field.

Once the user has selected an image, you can grab the selected image like this, assuming the field is called cover:

In your blueprint:

fields:
  cover:
    type: files
    max: 1

In your template you convert what is stored in the field to a file object using toFile():

<?php
if($image = $page->cover()->toFile()) {
  echo $image;
}

When you just upload files via a files section, you can assign a specific file blueprint to such a section and then filter all files of the page by this particular template:

Blueprint

sections:
  files:
    type: files
    template: cover
    max: 1

In your template you filter files/images by this template and then grab the first (since we limited upload to 1 in this section):

<?php 
if ($image = $page->images()->template('cover')->first()) {
  echo $image;
}

Thanks! I think I have it…

Page blueprint:

    fields:          

      cover:
        label: Main Featured Image
        type: files
        layout: cards
        info: "{{ file.dimensions }}"
        size: large
        template: cover
        multiple: false

      imageone:
        label: Image One
        type: files
        layout: cards
        info: "{{ file.dimensions }}"
        size: large
        template: imageone
        multiple: false

Template:

<?php    
    $image = $page->cover()->toFile();
    $image2 = $page->imageone()->toFile();
?>
<img src="<?= $image->resize(1600,1600)->url() ?>" alt="<?= $image->alt() ?>">
<img src="<?= $image2->resize(1600,1600)->url() ?>" alt="<?= $image2->alt() ?>">

This works and pulls the images into the correct places on the page template.

Two things I’m not sure of are:

  1. The file blueprint template you mentioned above, I have added a file to blueprints > files > cover.yml as ‘template: cover’ is mentioned in your code, but this doesn’t seem to do anything? If you click the image is just comes up with the default files template and not a specific one.

Screenshot 2021-04-23 at 20.11.20

  1. As $image = $page->cover()->toFile(); now references cover on this page, how can this be accessed from other pages? For example the cover is the main image on the news article page and I want the the cover image to the main news post image on the overall news page.

Current News Page:

<?php
    $news = page('news');
    $articles = $news->children()->listed()->flip();
?>

<ul>
<?php foreach($articles as $article): ?>
	<li>
		<a href="<?= $article->url() ?>" title="<?= $article->title()->html() ?>">
			<?= $article->image()->crop(400, 400, 80); ?>
		</a>
		<h2><?= $article->title()->html() ?></h2>
		<?= $article->intro()->kirbytext() ?>
		<a href="<?= $article->url() ?>">Read more&hellip;</a>
	</li>
<?php endforeach ?>
</ul>

Tying to figure out what to reference in the image tag to get the cover image only:

<?= $article->image()->crop(400, 400, 80); ?>

Thanks for your help!

In your loop, $articlerefers to the individual article, so the code is the same as before, with$pagereplaced by$article`:

if ($image = $article->cover()->toFile()) {
  echo $image;
}

In your code, you have removed the if conditions, but you should always use them, because you cannot rely on the images to exist.

1 Like

In a files field, you cannot assign a template via the template property, that only works for files sections.

If you upload files through your files field, then you can set the file blueprint to assign to the uploaded file via the uploads property, as per the documentation

(It pays off to always have a closer look at the docs and to play around a bit with the different options).

1 Like

That worked! Thank you!