Responsive images with WordPress Advanced Custom Fields
Advanced Custom Fields is an amazing (and free) WordPress plugin that turns it into a proper CMS and gives developers fine-grained control over how data entered by content administrators is handled and displayed. I love it.
I also love performant websites ergo responsive images, and I needed to find a way to combine them on a current project. The RICG have been working on a WordPress plugin that creates responsive images from featured image uploads and post content image uploads, but ACF is not core WordPress so misses out.
My aim here was to allow content administrators to only upload one image and the different sized images for srcset
would be created automatically by the CMS. Developer convenience isn’t a consideration, we still need to write the srcset
and sizes
attributes, this is all about avoiding having to tell our clients to crop an image to different pixel sizes.
Register new image sizes
I initially thought I would have to find a successor to tim thumb but Tom Blanchard pointed me in the direction of the add_image_size()
function on twitter.
For example (somewhat simplified):
add_image_size('blog-small', 200);
add_image_size('blog-medium', 600);
add_image_size('blog-large', 1000);
This function only creates new images when they are uploaded so if there are any already in the WordPress media library they will need to be regenerated. I used AJAX Thumbnail Rebuild and it worked fine.
Advanced Custom Fields setup
Set up an image field as normal in ACF, the only thing that is slightly different from what I normally do is to set Image ID Image Object as the return value.
The markup/PHP
To display the different sized images I used the wp_get_attachment_image_src()
function.
It takes an image ID and registered size name as parameters, and returns an array containing the image url, width, height and a boolean that indicates if it’s resized or not. We only need the url so to display an image the PHP is:
As /u/Yurishimo was kind enough to point out on Reddit, get_attachment_image_src
runs a database call each time it is run. It’s better to get everything at once in an Image Object and work off that.
$img['sizes']['blog-small'];
Extending that to markup:
<?php $img = get_field('image'); ?>
<img
srcset="<?php echo $img['sizes']['blog-small']; ?> 200w,
<?php echo $img['sizes']['blog-medium']; ?> 600w,
<?php echo $img['sizes']['blog-large']; ?> 1000w"
sizes="…"
src="<?php echo $img['sizes']['blog-small']; ?>"
alt="…">
And there you have it. Upload one image in ACF, get a responsive image on the frontend.
I don’t make a habit of writing PHP so if you can improve on this please do so in the comments or get in touch on twitter or email, links at the bottom.