I’ve been wanting to create a photo block for a while now. I’ve tried to fall in love with an image block from a block suite or even come to love the core block, but I’m too often frustrated that an image block takes too many clicks to use, or is just simply not flexible enough to accommodate non-standard layouts (such as a card layout).
A few months ago, I pulled the switch and asked my friend Ajay Dsouza if he’d like to help me develop a new (and free) photo block for the masses.
He asked how my photo block would be different. I told him my aim was to be able to have the block added and ready to publish in just 4 clicks. The block had to be easy to use but extremely customizable in all the right ways.
The result so far has been a wonderful learning experience, which I hope to share in this developer diary. I’d love to say the block is finished. It is not. But it’s mostly there.
It began with a wireframe
I’m a very visual person. I still like to do mockups and wireframes even though I don’t consider myself a designer. With other image blocks, you’re presented with several buttons, each doing a separate thing. This is shown below.
Rather than use this interface, I wanted a “large” drop zone for dragging and dropping photos in my photo block. I also wanted a way for a user to upload via file, via URL, use the regular media library, or choose an image from data parameters (if the block is used in a query loop).
The resulting wireframe and implementation are a marriage of all these ideas.
The goal of the wireframe was to present all of the various “modes” a user could be in without reliance on sidebar options. A user can upload a photo five different ways but still not be overwhelmed with options.
I began with the work on this initial screen first in order to get a proof-of-concept going.
For the icon set, I used Lucide.dev throughout the photo block and its settings.
I used FilePond for the uploader
The first UI element I tackled was the dropzone area, which I concluded needed to be a React uploader component.
The component had to be able to accept photos that are dropped, and also launch an upload dialogue if clicked on (dual purpose). I should also be able to modify the component and have a real-time preview.
As a side note, I did try to use the “amazing” Pintura editor in this project (for cropping and image editing), but the author doesn’t sell a license that can be used in a distributed product (I inquired how much, and it was prohibitively expensive).
The result is a neat upload experience if adding via drag and drop, via URL, or by launching the upload dialogue.
Uploading via URL
Uploading via URL had to be just as intuitive, so I decided to change the toolbar when the URL button is clicked, but still allow the dropzone for dragging or launching the upload dialogue instead if needed.
Here’s the URL input in action.
Uploading via the media library
Clicking on the Media Library button would bring up the media library modal and end up on the same edit screen as the other options.
The Edit screen
This brings us to the image edit screen. This is the screen a user should land on after selecting or uploading a photo.
The edit screen is designed to prominently display an edit/crop and replace option (two common tasks) and add some shortcuts for the alt-text and link settings in the toolbar.
I wanted as much as possible to be configured on the block itself and also in its toolbar. Not all users have the sidebar options open, so the toolbar and block interactions are paramount.
There’s a prominent “Replace” button, which takes you back to the initial image select screen. If you happen to click Replace and don’t mean to, there is a Back button, which will take you back to the last edited image (and back to the edit screen).
In addition to the Crop and Replace buttons, there are two popovers in the toolbar for accessibility and link settings.
Here’s the wireframe for the accessibility popover. It features inputs for editing the image title and alternate text.
Here’s how the accessibility popover ended up looking. I decided to group both the image title and alt text in one section, as the title can be used for accessibility reasons too.
The link options were a bit more complicated. The original wireframe I came up with has a custom URL picker. Not included in the wireframe are advanced settings such as an anchor attribute.
I settled on four buttons, with no link as the default. Clicking on the remaining buttons would bring up specific settings for the selected option.
Selecting “Full size photo” will reveal a shortcut to the media file and provide some lightbox settings.
Clicking “The photo’s page” will reveal a shortcut to the attachment page.
Selecting “Custom link” will show a URL input field, which also searches the database for any matching posts if keywords are entered.
All link options (aside from no link) have an advanced section where you can set the link anchor, have it pop up in a new tab, and other advanced link options.
I also have it so that if you do select “Open in new tab”, the REL attribute input will be filled in automatically.
Edit screen sidebar options
Let’s move onto the sidebar options for the Edit screen. The goal is to allow the block to be customizable but not overwhelm the user with unintuitive controls or UX.
For the sidebar options, I decided on tabs to mimic the direction that WordPress Core is taking with regard to splitting up items into logical sections.
In the main tab, there is an area for Presets, and I added duplicate options for the image title and alt text. I duplicated this functionality from the toolbar in order to make it clear that the title and alt text should ideally be filled out.
This next section looks very close to the way the standard core image block operates with regard to image sizes and dimensions.
I deviated from Core here a bit here and included all image sizes that the theme or plugins have registered.
Another notable difference is that the width/height controls are dynamic and maintain their aspect ratios when edited.
For the image styles, you can adjust the background color, image opacity, adjust the blur, and also add a drop shadow.
For CSS styles, I’m using CSSGram to add a CSS filter to the photo in order to change its appearance. I coded it so that hovering over an item will show a preview of what the image would look like with the filter applied.
As far as sidebar dimension options, I had to create several custom controls in order to capture all of the dimension data I needed to style the image. I tried to mimic core styles and behavior as much as possible. I ended up coding two custom dimension controls for the padding, margin, border, and border-radius.
Here’s how it ended up coming out. It’s a lot of functionality in a very confined space. Each control can also be adjusted per media breakpoint (mobile, tablet, desktop). You can see the icons for each in the animated gif below.
For this next section, I borrowed heavily from the way GenerateBlocks’ image block handles container sizing.
The image out of the box is designed to be fluid and not necessarily have any constraints. However, having sizing controls allows you to be much more creative in the way you can display images. For example, if you’re using the block to display author avatars, you can set these values to have a set width and height with positioning via the object fit settings.
Here’s an animated gif of making a circular image.
You’re also able to specify min and max height parameters per breakpoint.
As far as advanced options go, I’ve included the ability to add CSS classes to the
img tag separately for more advanced styling.
Another feature I borrowed from GenerateBlocks is adding custom data attributes.
There is also an option to prevent lazy loading the image, preventing right+click saving, and the ability to show and hide based on a breakpoint.
The crop screen
For the crop screen, I wanted to use an intuitive cropper and have the cropper behave the same as Photoshop or Affinity Photo.
The toolbar allows you to unlock the crop aspect ratio (for a freeform crop), select an aspect ratio, and also allows you to rotate the image.
For the “Custom” option for aspect ratio, you can manually add in your aspect ratio.
When first visiting the Crop screen, the full-size image loads so that you can crop the original image.
Clicking “Save Changes” will crop the image and save any rotation.
If the crop is not desirable, an “Undo” option shows in the toolbar so that you can revert the crop.
Being a photography block, the caption is very important for describing the image and giving appropriate credit. For the majority of the image blocks I’ve tried, the caption is an option in the toolbar that could be toggled on or off and seems a bit of an afterthought.
For the photo block, I imagined a fully-featured caption where the caption would be (towards the bottom). This way, adding a caption is more immediate and there’s no need to jump between the interface unless you want to change caption positions.
From an architectural perspective, I made the caption its own block. This made for a more configurable caption and opens the door as far as customizations. It also helps cleanly separate the caption functionality from the photo controls.
By default, a user is given a single-line caption. This is what the majority of users will be used to as far as captions go.
However, if you have a more complex caption, you can switch modes and use blocks to create your caption.
The multi-line caption is actually a collection of blocks. Not wanting to open up the caption wide-open, there is currently a set list of enabled blocks for the caption. I did this so that I could provide some base styles for the included components.
When in multi-line mode, I have provided an option called Smart Styles, which will lay down a base style for all of the supported inner blocks.
You’re able to adjust font families for paragraphs and headings. Currently, only common web fonts are available.
Four color choices are presented, which will apply to all available inner blocks. You can also increase or decrease the base font size to give the caption more room.
For single-line captions, the options are a bit more straightforward but the caption is less flexible.
You’re able to adjust the typography, background color, link color, and link hover color.
I coded a custom popover component for the typography section, which can also be adjusted per breakpoint.
Moving onto the Styles tab in the Inspector Controls, you’ll find the same dimension and layout settings as you’ll find in the parent photo block.
For the Advanced sidebar options, you can set the CSS class, add data attributes, and display the caption based on breakpoints.
Whether in single or multi-line captions, you’ll notice you can adjust the position of the caption.
There are three choices: Top, Overlay, and Bottom.
By default, the caption is positioned at the bottom of the photo. You can choose “Top” to position the caption above the photo.
You’re also able to position the caption over the photo, also known as the Overlay position. Selecting this will center the caption over the photo. You’re able to select an overlay type and adjust the caption’s text, positioning, and color settings.
The data screen
The photo block has data built-in and allows you to select where the image is coming from. This is so that you can use the photo block within the Query Loop block.
When on the data preview, you can specify a source for the alt text, title text, and link source.
You can also set a fallback image and set the image size using the sidebar options.
And lastly, you can choose a dynamic caption.
With the block being more or less complete, I still need to code the front end of the block. After that, lots of testing, and then finally, a release on WordPress.org.
If you’re interested in the Photo block, you are welcome to sign-up for my newsletter, where I’ll share updates on the progress.