Best way to create responsive images in the block editor

Hi

This is my current template version which is fine.

    <picture>
        <source srcset="<?php if($image = $page->featureimagelarge()->toFile()): ?><?= $image->url() ?><?php endif ?>" media="(min-width: 1300px)">
        <source srcset="<?php if($image = $page->featureimage()->toFile()): ?><?= $image->url() ?><?php endif ?>" media="(min-width: 760px)">                
        <img src="<?php if($image = $page->featureimagemobile()->toFile()): ?><?= $image->url() ?><?php endif ?>">
    </picture>

I’d like to use the panel to do the equivalent and was wondering if modifying the gallery block is the best way to do this, but the gallery loops and I’d ideally like to have the option for two or perhaps three images, as opposed to just one that is edited, for art direction purposes. I’m more of a designer so I’m fine with HTML and CSS, but struggle with the best way to do this in PHP.

For clarification I’m currently using the above on a portfolio page for the project ‘hero’ image, but would also like to add additional responsive images on other parts of each project, in the panel as blocks.

It seems like the gallery is the best option, as this is already setup to allow you to add multiple images, but how would I tailor the PHP to reference the images like my example above.

The accordion example from https://www.youtube.com/watch?v=XbFoF92ZoyY&t=790s seems to be the basis of what I need to do but I’m struggling to adapt it. That example is also used on the ‘About’ page but I’d like to be able to use it everywhere.

Thanks in advance for any help.

I would create a custom block type with three separate files fields. Each set up to accept max one image. Your current template could then be adapted to be the block snippet.

With that, you’ll first get a very basic entry in the blocks list in the Panel, no real preview. You could either see if preview: fields is sufficient for your use case. Or if you’ll need to create a custom preview for your custom block

1 Like

Thanks. It felt like the accordion example I saw in the custom block video was the basis of what I needed. I’ll give that a try. Is there anything special I need to do in the config for the field to accept images? At this stage I’m not bothered by a preview as long as the output HTML is what I need.

If it’s just you editing it, probably not because you know that you’ll just select one file and that it needs to be an image. If other editors are involved, take a look at the files field options to learn how to limit the number of files, only allowing images to be selected as well as restricting uploads to images.

1 Like

So I’ve made progress but have introduced a few issues.

So this works as I expected in my responsive.php, but currently I have to add the absolute path to the image in the panel, so ideally each would use the image picker and the URL would be automatic.

<?php foreach ($block->items()->toStructure() as $item): ?>
<figure>
	<picture>
		<source srcset="<?= $item->desktopimage() ?>" media="(min-width: 1300px)">
		<source srcset="<?= $item->tabletimage() ?>" media="(min-width: 760px)">
		<img src="<?= $item->mobileimage() ?>">
	</picture>
</figure>
<?php endforeach ?>

More of an issue is that when I added the following using https://www.youtube.com/watch?v=XbFoF92ZoyY&t=790s as a start point

    fieldsets:
      - type: text
      - type: image
      - type: responsive
        preview: fields
        fields:
          items:
            type: structure
            fields:
              mobileimage:
                type: text
              tabletimage:
                type: text
              desktopimage:
                type: text

The default blocks stopped working so all my previously added block content in the JSON was lost. I was able to retrieve it as I had the file open in my editor but how would I update that so that 1) I can use the default image picker behaviour and 2) enable all the default block types. I added text and image in but the image doesn’t function correctly.

Thanks.

I would recommend not to use a structure field, but put all three fields directly in the fields: option of the block. If I didn’t understand you wrong, you want one block to have 3 images for the different sizes, not multiple sets of 3 images in one block.

Then I would recommend to use type: files and not type: text. That gives you the file picker field.

Does it make a difference for the default blocks if you write just - text instead of - type: text?

And lastly, always have a backup please when developing on your content. So you don’t rely on the content file being open in your editor as backup. :pray:

1 Like

Brilliant. I removed structure (I’d just copied this from the custom block video), set the type to files, and yes just ‘- text’ restored the default block behaviour. Much appreciated.

I should be able to get the correct path to my images working, but will come back if not.

Thanks again.

There is also an (yet undocumented) blocks.fieldsets config option that allows you to re-define the default set of fieldsets. However, then you shouldn’t define your custom block directly there in the blueprint (as this will always overwrite the default set), but would need to register it via a custom plugin https://getkirby.com/docs/reference/plugins/extensions/blocks#full-block-plugins__adding-a-default-blueprint-and-snippet.

1 Like

So I think I was a bit optimistic taking my existing template code and adapting it slightly. What do I need to do with the following to use the files? I’m seeing the correct HTML, just no path to the image. Thanks.

<?php foreach ($block->items() as $item): ?>
<figure>
	<picture>
            <source srcset="<?php if($image = $page->desktopimage()->toFile()): ?><?= $image->url() ?><?php endif ?>" media="(min-width: 1300px)">
            <source srcset="<?php if($image = $page->tabletimage()->toFile()): ?><?= $image->url() ?><?php endif ?>" media="(min-width: 760px)">                
            <img src="<?php if($image = $page->mobileimage()->toFile()): ?><?= $image->url() ?><?php endif ?>">
	</picture>
</figure>
<?php endforeach ?>

$page->desktopimage() etc. should be $item-> as these fields are on the block not the general page.

Also probably better to wrap the if statements around the full tag:

<?php if( $image = $page->desktopimage()->toFile()): ?>
<source srcset="<?= $image->url() ?>" media="(min-width: 1300px)">
<?php endif ?>
1 Like

It’s OK, I fixed it by changing $page to $block. All working as required.

Just noticed your reply, so I’ll try that too.

This works for me. Which part should I change for $item-> ? I tried just replacing $block-> and it didn’t work. Thanks.

<figure>
	<picture>
            <source srcset="<?php if($image = $block->desktopimage()->toFile()): ?><?= $image->url() ?>" media="(min-width: 1300px)"><?php endif ?>
            <source srcset="<?php if($image = $block->tabletimage()->toFile()): ?><?= $image->url() ?>" media="(min-width: 760px)"><?php endif ?>                
            <img src="<?php if($image = $block->mobileimage()->toFile()): ?><?= $image->url() ?>"><?php endif ?>
	</picture>
</figure>

True sorry, I was mistaken from the foreach loop. But that was related to the old structure field. I thought you renamed $block to $item.