Automatic responsive images in WordPress
NB: This article was originally posted to the Viewport Industries blog which is no longer active (the company is of course, rather the blog didn’t get updated much). It’s archived here as rather unbelievably it gets referenced a lot. Thanks for reading – Keir
As Elliot mentioned in our first post we wanted to try out a few relatively new techniques on this site, the main one being the inclusion of Josh Emerson’s Responsive-Enhance script to serve resolution-dependent images.
The simplest way to see the script in action (if you are using a desktop browser) is to resize this screen so that it’s very narrow and hit refresh; all being well the image above should turn into a black and white version, physically smaller in terms of dimensions and file size. Now slowly stretch the screen out again and you should see the colour version kick back in. Josh’s script cleverly replaces the lo-res version with the full size colour version — nice and easy.
Getting it to work
The beauty of this script is its simplicity. Here’s all you have to do:
- Include a link to the script in your document
- Create the relevant img elements with your lo-res image as the default src
- Add a data attribute called ‘data-fullsrc’ which has a path to your full size image
Setting it up
Sounds easy and it is. Here’s how our img element looks with the addition of the required data-fullsrc attribute:
<img id="digest-header" src="<?php bloginfo('template_directory'); ?>/img/heading-digest.gif" data-fullsrc="<?php bloginfo('template_directory'); ?>/img/heading-digest-large.jpg" alt="Digest logo" />
In case you’re not familiar with WordPress, the
<?php bloginfo('template_directory'); ?> will be replaced by the current themes directory path.
We are using the jQuery selector here but you could just as easily use:
The function takes the img element and the screen width as arguments. It’s that simple. You can also get it working quite easily for images that use a particular class or are contained within a particular section. For example, using jQuery, you could do something like:
responsiveEnhance($('article img'), 400);
This would run the script over all the images contained within an article element.
Automagic black and white
Setting it up for the home page was simple enough, but having fallen for the technique we wanted our blog header images to follow suit. Hand crafting different versions of the header image for each blog post would result in a lot of work (for Elliot!), so we initially avoided the idea. However, on closer inspection it turned out that we could auto-generate these images using a couple of handy WordPress filters and some (new to me) PHP functionality.
At this point a rather large hat tip must be doffed to c.bavota, whose script got me on the right path. The one I actually use is virtually identical apart from a line or two to handle file naming conventions.
We have created a gist over on GitHub so you can grab the function for yourself. The embed doesn’t currently play that nice with our design so have a quick look and head back for a quick explanation.
The first thing to note is the following function call:
add_image_size('thumbnail-bw', 400, 0, false);
This tells WordPress to create a new image with a name of ‘thumbnail-bw’ at 400px wide for every image that we upload, providing it is 400px or wider. The final two arguments dictate height and crop. In this case we don’t specify a height as we want it sized proportionally, and for crop we specify false which equates to ‘soft proportional crop mode’. With that set up we can go about manipulating our new ‘thumbnail-bw’ image.
Next you will notice the
add_filter('wp_generate_attachment_metadata','bw_images_filter'); function. A filter is described as follows in the WordPress codex:
Filters are functions that WordPress passes data through, at certain points in execution, just before taking some action with the data (such as adding it to the database or sending it to the browser screen). Filters sit between the database and the browser (when WordPress is generating pages), and between the browser and the database (when WordPress is adding new posts and comments to the database); most input and output in WordPress passes through at least one filter. WordPress does some filtering by default, and your plugin can add its own filtering.
Essentially what filters allow us to do is modify ‘stuff’; i.e.: text or, in our case, images. There’s so much you can do with filters, but that’s another post entirely.
So by filtering the creation of the meta data (every image has associated data that we can use in a variety of WordPress functions in the database) associated with an image we can create our own black and white version for use with our responsive image script.
bw_images_filter does all the heavy lifting for us and is called every time
wp_generate_attachment_metadata an image is uploaded. Without going into too much detail, here’s what happens in the function:
- The function receives an array of file meta data relating to our most recently uploaded image. This is passed in from our filter call. This array contains all the details we need to start manipulating our image.
- Next the image is grabbed using
wp_load_imageand assigned to a variable
- The function then runs the image through the native PHP function
imagefilterto turn it into a black and white version
- We then save out the modified version and change the file name by adding the appropriate extension with the -bw suffix, e.g.:
filename-bw.png. It’s worth noting that the originally uploaded image will remain on your file system, but you could easily modify the function to delete it.
- Finally we return the new meta data, which WordPress adds back to the database
It’s a pretty simple function but does the job well. This only works on new uploads but you could modify this function to iterate over your existing files without too much trouble.
Your needs will dictate what kind of logic you employ in your archive or single template. Whilst I have included links below to the loop logic we use on this site as well as the JS function call, I doubt a simple copy and paste will work on most sites. However, simple modifications to relevant class names should be pretty straightforward.
- Gist showing the functions required to get the src of your black and white image set to a variable you can use in your template
- Gist showing the jQuery call that makes it all happen. Note: this is specific to our templates and you will likely need to modify it for your own needs and class names.
Undoubtedly the way we deal with images and responsive design will change in the next few months, but we are very happy with this approach. It works well, is easy to integrate into WordPress, and allows us to have a bit of fun with making them black and white.
I hope it hasn’t been too hard to follow. If you have any questions please feel free to drop a comment below.
Update – August 2012
We removed the black and white element of this script in version 2 of this web site. The principal remains the same but if you resize the browser and refresh you will now see a smaller full colour version of the image. Apologies to those who read this, resized and thought that it wasn’t working.