Managing Images in your Custom Gutenberg Block

Abridged Transcript:

 So a while back I wrote this tiny JavaScript component to use in the WordPress block editor that basically replicates one of my favorite PHP functions in WordPress, wp_get_attachment_image(). wp_get_attachment_image() is great because you pass it the ID of an image in the media library and maybe the size or some other attributes, and you get back like the full image element with, you know, Sizes, alt text, all this sort of stuff.

Lazy loading and everything. So if you’re building sites with advanced custom fields and stuff, I find you’re using this a lot. But I actually have been using it when I build dynamic blocks, which use PHP on the front end and JavaScript on the backend. So I needed something on the backend that was kind of a JavaScript version of this when I was passing that image ID around and wanting to render it. So that’s what led to me building this little component right here.

It’s not a full featured version of it because it doesn’t include some of the things that we don’t need on the front end of our site. But you essentially pass it in image ID and it renders out a little image act image with all the attributes inside.

So let’s use this in a block and see what we can do with it.

Preview of our Block

I’m here on a local site that I’m building, and what we’re gonna do is look at the final block, and then we’re gonna go through some of the pieces of it and see how we built it. So it’s called the Double Image Block. And the way the double image blocks works is you get to pick one image here.

And then you also get to pick another image here. So we’ll pick some images from our media library. We’ll put the moon up here in the front. We’ll pick the surface of the moon in the back. And the way the image works is when you’re on the front of the site, if your mouse goes over it the front image fades away.

The background image shows up. So we see this a lot on like team pages where you have a picture of the CEO and then you hover over him and he’s making a goofy thing, or he is dressed like a sports fan or something fun like that. So it’s pretty common. Thing I’ve built a lot of times and, you know, there’s ways you could probably do this with native blocks or, you know, inner blocks, things like that.

But in this case, I wanted to be able to just edit one image right here when I was focused and then edit another image over here. So let’s take a look at what this block looks like.

Create Block package

So what we’re looking at here is a plugin that I generated with the npx @wordpress/create-block example-image-block --variant=dynamicCode language: Bash (bash)

It creates all the files, you tell it what kind kind of block you need, and it kind of makes all of that for you. So I use that to generate the scaffold. It comes with package.json. And it comes with 10up Block Components

But we made a few changes. The first change is I actually installed a dependency. This is an open source package from 10Up called Block Components, and we’re gonna use this because it comes with a couple extra components that are really nice. We’re using the image picker, which we saw lets us pick our image.

And this media toolbar component will also be using, which lets us add some stuff to the block toolbar. So this is our one dependency. We just literally run npm install --save @10up/block-components. And it shows up in your build process and you can just use it throughout your project. So I can see it’s here as my only dependency.

And if you were to npm install, it’s just ready to go anytime you build your scripts. So we’ve run npm start, and I can see in my terminal over here that my build process is running. Let’s start with our block.json file.


So in our block.json file, what we’re looking at here is. The title of our image, the icon, the descriptions and stuff that we set up.

Here’s what we’ve changed right here. We’ve added some attributes. These are two values that are gonna get saved. One is the foreground image and one is the background image. And they’re both integers because again, we’re getting the image id, the kind of number of what image it is in the media library, and that’s all we’re saving.

{	"$schema": "https://schemas.wp.org/trunk/block.json",	"apiVersion": 2,	"name": "wpdev/double-image",	"version": "0.1.0",	"title": "Double Image",	"category": "widgets",	"icon": "format-image",	"description": "Example block scaffolded with Create Block tool.",	"supports": {		"html": false	},	"attributes" : {		"foregroundImage": {			"type": "integer"		},		"backgroundImage": {			"type": "integer"		}	},	"textdomain": "double-image",	"editorScript": "file:./index.js",	"editorStyle": "file:./index.css",	"style": "file:./style-index.css",	"render": "file:./render.php"}Code language: JSON / JSON with Comments (json)

The render.php file

And similar to like an ACF approach, we’re gonna use that to render it on the front end. Speaking of render, let’s jump over to our render.php. This kind of gives you an idea of what we’re showing on the front end of the website, which is really pretty simple. We have just a wrapping div. It’s got all the class attributes kind of handled by WordPress for us, and it’s literally just gonna check for those two attributes that we talked about.

<?php/** * Block render callback. * * @param array $attributes The block attributes. * @param string $content The block content. * @param WP_Block $block The block object. * * @<besr-highlight>package</besr-highlight> wpdev */?><div <?php echo get_block_wrapper_attributes(); ?> tabindex="0">	<?php	if ( isset( $attributes['foregroundImage'] ) && $attributes['foregroundImage'] ) {		echo wp_get_attachment_image( $attributes['foregroundImage'], 'full' );	}	if ( isset( $attributes['backgroundImage'] ) && $attributes['backgroundImage'] ) {		echo wp_get_attachment_image( $attributes['backgroundImage'], 'full' );	}	?></div>Code language: PHP (php)

And if they work, we’re gonna spit ’em out on the front end with wp_get_attachment_image. So it’s really just a div with two images next to each other into him. So now let’s build out that editing interface that we saw using this package and some of these other packages. So let’s start with the main foreground image.

Starting our edit.js file

We’re gonna need to set up a couple of things like our props. Then we’re gonna wanna grab our props. I don’t need this one, but we want our attributes and we want the function to set our attributes. And then I know we have. Two attributes. We have foreground image and background image. So we’re just gonna pull those out so we’re have them ready to go.

And then we’re gonna need to basically have some functions to set those images when they’re selected. But let’s start, let’s get rid of this default stuff, change this to a div, and we’re actually gonna use that image component from 10up. So we’re gonna start by using this image component from 10Up.

10up’s Image Component

So you can look at the documentation here, but you’ll see basically there’s a bunch of parameters. We need to pass it and we’ll need some functions to handle things like setting the image. So we’ll start with that. We need our size, which we’re gonna just basically say is a full size image, and we need our onSelect, which basically means what do we do when it’s time to select the image? We’re gonna separate that out into a function, which we’ll say set foreground image. The nice thing is I do have copilot running, so if I come up here and I start typing it already basically knows what I need to do to set that.

            <BlockControls>                <MediaToolbar                    isOptional                    id={ foregroundImage }                    onSelect={ handleForegroundImageSelect }                    onRemove={ handleForegroundImageRemove }                />            </BlockControls>Code language: JavaScript (javascript)

Which is essentially set the attribute of the foreground image with the ID that’s gonna get passed back. So we basically have a closed loop here. So we have a foreground image that tells us what the idea is. If they select a new image, that image ID gets sent back to the foreground image. So that’s gonna load our main image right here.

And then we also just gotta make sure we import that image from our 10 up block components. So let’s save that. Let’s jump over to our WordPress site. Let’s take a look. So far, if I start typing in my. Double image block and boom, I have that image component set right there. It already works. It does that first pass, but there’s a few more things I need to do.

BlockControls and MediaToolbar

So I want to add some settings here because once I’ve set the image, I wanna be able to swap it out if I’m using a different image. So that’s where block controls comes in. So block controls is something we’re actually gonna get straight out of the WordPress block editor, cuz it’s something that we use to pass controls in that.

And what we’re actually gonna pass it is another thing from that 10up components package. So in that 10up components package, you’ll notice they mention here that you need to use this media toolbar component. That’s something that we can do inside of our block controls and we can pass it here. So I’m actually gonna just copy and paste it in.

And what this means is it’s just gonna put some buttons inside that toolbar above our block. Anything that you put inside block controls kinda shows up on your block. So we just need to. Handle some of these same things. And then we just need to handle foreground, image remove. So the same id cuz it’s dealing with the same image, it’s dealing with the same on select.

And then we just need to set up this function right here, which basically says what happens if I remove it? And co-pilot will basically have us here. Basically we’re knowing it out so, And one last thing that we need to do is we actually need to import that from our 10 up. So media toolbar, we gotta know where it’s coming from, so now it’s imported and our block controls is imported.

So now we’re back in editor. Let’s just try to add that image one time, double image. And now look, I have an ad image here that’s the same thing as this. If I select an image, I can see that they’ve turned into these buttons to replace or remove the image. It’s just good ui. So now let’s add our background image.


So the way we’re gonna do the background images, we’re actually gonna add that in to the sidebar using Inspector controls. So Inspector controls is essentially that sidebar panel for any block and you have the chance to use that for you know, adding your own settings. And we just have to make sure that we import it.

Inspector controls from the block editor. And then we’re actually going to use a couple WordPress components here just to match the styling. So WordPress has these components, one’s called Panel, PanelBody, and you can see here, it kind of knows where we’re going with this. And we’re gonna do inside of that a PanelRow, which is helpful if you wanna break a few things.

And then let’s just close these real quick. And what we’re gonna do inside of here is we’re essentially gonna use the same component, the same image component. But this time we’re gonna use this one to set the background image. So anywhere here where I say foreground image. Now this’ll be for a different value called background image, and that means we’re gonna need to create a new function for setting that background image.

So let’s go over here. Let’s just let copilot take care of it for us. It knows what we need to do. Set our background image. Pass the id. This shows up in a PanelRow. So let’s do a little save and then actually we’re going to pass one more thing. There’s something called labels we can pass. And what we really want is to just give it a title, and that’s just in case we want to see what it looks like.

And then these components here, we just gotta import those two. And those are not actually from the WordPress block editor. Those are from WordPress components, right? So Block Editor is really like a lot of things that are specific with the block Editor. Components is more just like generic UI that’s not as functional.

These are all functional. These are just kind of generic UI that we’re gonna use. Okay, so let’s try this out in our editor real quick. Let’s add a double image block, and then now we can see, we have this one here. Upload a file, pick one from your library. And then we have this sidebar double image. This is our inspector controls.

Here’s our little panel body, and that’s where we get to set our background image. So we get to set one image here, right? And then we have a completely different one over here.

Adding a remove Button

But there’s only one problem. Once I’ve set that image, I don’t have the media toolbar here to remove it or replace it. So we’re actually gonna use that.

We’re gonna use a similar component just to give us an option to remove the background image. So we’ll head over to our panel body and our panel row and we’re gonna make another panel row. And we’re actually gonna add a button. And this is a WordPress button. So we’re gonna have to import this component, but we can already tell what our onClick‘s gonna be.

Our text for the button and our on click event for the button. So when we click on that button, that background image is gonna get removed. Let’s just go here. Copilot knows what we’re doing, and boom. So when we click this button, Take our background image attribute and set that to Noel. And just to be clear, let’s do variant.

This basically is kind of like some design stuff. What does it look like and isDestructive, which kind of tells WordPress to highlight it nice and red. Let’s take a look at how that looks. And of course, the last thing we have to do, make sure we import that button component.

Add our double image block. Now we have this guy here. There’s nothing to remove. We could probably put that in a conditional, but for now, let’s just make sure it works. We set an image, we remove it, we can set a new one. I think that works pretty well.

Our custom AttachmentImage component

And last but not least, we’re actually gonna use our attachment image.

Component here. So this is what we started off with, right? This is basically a way to say, I want to just show an image. I don’t wanna need it to be editable. I don’t need all the extra functionality. I just need that kind of classic. Show me an image if I pass you an image id. So we’re gonna use this attachment image component over here, and what we’re gonna do is we’re gonna do a little conditional, let’s just check if the background image works, all right?

And if the background image is there, then whoops. We’ll do our attachment image. And it already knows. We want that image ID and we want that size. So we’re basically saying if there’s a background image, use our attachment image function, and then we just gotta make sure we import it up here. So let’s add it up here with all of our other imports.

Attachment image from attachment image at our import here, we actually don’t. So we’re gonna import that from our JavaScript file that’s sitting right here. And use that as a component. All right, so let’s jump over to the front end. I think we got everything set up. Let’s find out. We’re gonna add our double image.

Let’s add our foreground. That’s the moon. Let’s add our background. That’s this one right here. And we can see that it’s remove image, replace. Let me remove focus, and when I hover, yep, there we go. What’s happening here is both of the images are rendering, and thanks to our css, we can see that kind of effect that we wanted.

And what’s even best about this is when I go to edit it, I can edit this image here, I can edit this one here. I don’t have to deal with how do I edit the image that’s behind there because I’m using my one element to just render it, and I’m using another one over here to handle the editing of it. And so that image ID attribute gets saved and passed around here.

And then, When I go to the front end of my site, it’s gonna use that same thing. It’s just gonna pull it out of an array. Some easy php. So let’s save this. Let’s jump over the front end and boom, there’s our WP attachment image ID right there.

Final Preview and wrap up

So that’s a quick walkthrough of how I would use this attachment image component and a function.

I think it’s kind of cool we got to see a lot of other things, like some of the block controls, inspector controls, and. Some of those 10 up components and, you know, at the end of the day a lot of this is, is pretty similar to any sort of other block UI you’ve built. And, you know, because we have one style CSS file being loaded here, it’s handling all of the opacity and transforms.

And then you’ll be able to look at all of this code. There’s gonna be a link at the bottom of the video to GitHub, so you can take a look at all of this here and comment. Do you have any questions?

Learn Modern WordPress Development

I’m sharing the best resources and tutorials for developers building in and on the block editor.

4 responses to “Managing Images in your Custom Gutenberg Block”

  1. James S Fallon Avatar
    James S Fallon

    You left out one thing. For us newbies, how would I get this block working on a stock WP install with say the Twenty Twenty Four theme installed? I know enough to be dangerous. Is this code something I can paste directly into a template or someting? Please advise, thanks.

    1. Brian Coords Avatar
      Brian Coords

      Well you could definitely download the repo and install it on your site as a plugin, and it should work.

      Direct link to that download: https://github.com/bacoords/example-image-block/archive/refs/heads/main.zip

  2. James S Fallon Avatar
    James S Fallon

    Found it and implemented it. Thanks for directions.

    I taught myself to play guitar using tablature and realized years down the road that I should have learned theory etc. I kinda messed up the same way with Website building. Started w/ Microsoft Frontpage years ago, when I heard about WordPress powering so much of the internet I tried to learn. I was baffled from the start. So then I ventured off into Themes and Page builder land, and although I learned a lot it feels like I should just stick with stock WordPress to REALLY learn.

    So when Guttenberg came along, particularly this latest version, the light has kinda come on. Now I am dropping everything to do this. I am a massively slow learner and am always blown away at the level that you guys “perform” at. I will probably never be the code guy, but I can always figure stuff out in the end.

    And now with AI I have a teacher with endless patience that can teach me all day long. It would be great if the help section for Guttenberg was trained particularly with a Co-Pilot. Although I get lots of help this way, I bet it could be much more specific and better, hopefully this is all in the works.

    Thanks again, and here’s my result on this practice page. Right on top of the Bento block I just learned to make w/ help from Jamie M. https://jamesf257.sg-host.com/procreate-site/

    1. Brian Coords Avatar
      Brian Coords

      I’m the same way (with guitar as well), but I think it’s normal. You learn something the easier way and then you hit a ceiling where you have to decide if you’re going to go back and learn all the fundamentals or just stay at the same level.

      As for AI, I’ve heard good things about https://codewp.ai/ but I’ve never tried it out. Copilot inside VS Code has been getting better and better with WordPress stuff.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.