There was once a time, not that long ago, where a website’s content was almost entirely text. Images existed, but were not nearly as prominent as they are in our post-Bootstrap world. In the time between these eras there have been major evolutions on how images can, and arguably should, be handled, which brings us to the age of Responsive Images.
Images are going through a renaissance, moving beyond purely making choices on which image flows best or if a particular photo vibes with the aesthetic of a given site. Using responsive images developers now have the ability to deliver imagery that is sized appropriately for a given user’s device. Responsive images are simply images that are able to respond to the needs of a user’s environment.
Adding a responsive image strategy to your development plan is worthwhile, because it will lead to both faster page load times, and lighter payloads to be delivered to your user’s browsers. Faster load times mean fewer abandoned pages, and more time spent on the page by end users. At the Brick Factory we have seen seconds shaved from load times, and megabytes shed on projects built with responsive images using the techniques below.
Now you know the why of responsive images, but what about the how. There are essentially two paths for adding responsive images to your site: (a) adding the srcset and sizes attributes to <img> tags, or (b) combining the <picture> element with the <source> element.
If you are implementing responsive images with performance increases as the primary goal, then stick to using srcset with <img> tags.
1 2 3 4 5 |
<img alt="An oak tree." src="oaktree-lowres.jpg" srcset="oaktree-highres.jpg 2x" > |
In this example you can see the srcset attribute contains a suggestion for 2x. This is an indication of what level of pixel density a device supports. It is also common to write srcset suggestions representing the amount of horizontal space the image may best fit. Those suggestions only require a number suffixed with a w (eg: 420w).
If you would also like to change the images wholly based on queries, use <picture> with <source> elements:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<picture> <source srcset="forest.jpg" media="(min-width: 1000px)" /> <source srcset="tree.jpg" media="(min-width: 600px)" /> <img src="foliage-closeup.jpg" alt="Oak Tree" /> </picture> |
Another way to use the <picture> element is to serve new and/or alternative image formats. There are a handful of newer image formats available now which offer even greater lossless compression than our trusty stand-by the jpeg. If your server supports any of these you could also see a performance increase. Below is a simple example offering a webp image with a jpg fallback.
1 2 3 4 5 6 7 8 9 10 |
<picture> <source srcset="foliage.webp" type="image/webp" /> <img src="foliage.jpg" alt="Oak Tree" /> </picture> |
At the end of the day, either is fine, and will get you where you’re going, but if you’re feeling stuck, our good friends over at CSS Tricks have a handy dandy decision tree.
Now that you have an idea of why and how to set-up responsive images the question is how do you actually work them into your real life projects. Here at the Brick Factory, we spend a lot of time developing for WordPress, and pride ourselves on using the platform to its fullest. Responsive images were added to core in WordPress 4.4, since then, implementing responsive images has been a straightforward matter whether you’re using traditional PHP templates or using a Twig based framework.
Oftentimes we must reckon with the fact editors don’t always have the tools on hand to prepare perfectly scaled images. Thankfully, WordPress comes prepared to handle this very situation by allowing developers to register common image sizes using add_image_size() within the theme’s functions.php file.
There are a few image sizes defined by default within WordPress, these include: Thumbnail, Small, and Large. It’s important to define image sizes which will fit into your goals, otherwise the WordPress utilities for srcset and sizes will only take those defaults into account.
When deciding which image sizes to include in your theme it is also important to remain aware of the server space required for image hosting. WordPress will dynamically create all of the defined image sizes upon upload, which means multiple image files will be created for every one you upload. So just be thoughtful about which image sizes matter to you, and everything will be alright.
Images in WordPress can typically be categorized as content images and/or theme images. The former represents those images that are inserted into posts and pages by editors, while the latter are those that exist within a specific theme. Oftentimes these images are primarily decorative, but as is the nature of development this is not always true. There are several ways you can display responsive images within WordPress whether they were uploaded by an editor or explicitly added to a theme.
Since WordPress 4.4, images inserted into a post, and even using the Gutenberg image block, will include a default set of srcset and sizes attributes. These are based on the Image Sizes defined by your theme. At this point if you have already established a basic set of image sizes then the default settings will work out pretty well.
1 2 3 4 5 6 7 8 9 10 11 |
<img class="size-medium alignleft" src="https://blog.thebrickfactory.com/uploads/2021/05/example-300x200.jpg" alt="alternative text describing the image" width="300" height="200" srcset="https://blog.thebrickfactory.com/uploads/2021/05/example-300x200.jpg 300w, https://blog.thebrickfactory.com/uploads/2021/05/example-768x513.jpg 768w, https://blog.thebrickfactory.com/uploads/2021/05/example-1024x684.jpg 1024w" sizes="(max-width: 300px) 100vw, 300px" > |
However, if you would like to have more control over the sizes attribute that is completely possible through the wp_calculate_image_sizes filter. This post is a great resource for understanding how to take full advantage of this filter.
The default method for writing custom WordPress templates is still to use HTML with PHP mixed in to pull the component data that you want to display. More often than not, if an image is included in a PHP template, it will be in the theme files rather than uploaded to WordPress from the Dashboard by an editor.
In this scenario you can simply choose which method (srcset or picture) you’d like to use. Below is an example which takes advantage of core WordPress functionality by allowing you to display a post’s thumbnail image with the addition of srcset and sizes attributes. It’s notable here that the functions will generate an HTML string ready to be printed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<?php /** * This example would work best within The Loop on post types utilizing * featured images. */ //WordPress has several helper functions available for making this easy $featured_id = get_post_thumbnail_id(); $featured_meta = wp_get_attachment_metadata( $featured_id ); $featured_image_element = get_the_post_thumbnail('hero_full'); //This function returns an HTML element string. Simply echo out to display. $featured_image = wp_image_add_srcset_and_sizes( $featured_image_element, $featured_meta, $featured_id); echo $featured_image; ?> |
At the Brick Factory we use both WordPress and Drupal to build sites, which is how we arrived at the decision to work Twig into our WordPress starter kit. By doing so, our Front End team can focus on a single template language environment to work from.
Our Twig implementation of choice is baked in using Timber. Our Twig templates often stretch beyond just basic page layout and into more complex page components using Advanced Custom Fields, Custom Gutenberg Blocks, and oftentimes both. Timber makes it very simple to pull image data from a Post or Block’s custom fields which we can then manipulate in the template to fit our needs best.
Here you can see an example of implementing srcset and sizes into a Twig component for hero images.
1 2 3 4 5 6 7 |
{% In this example ‘hero’ represents the Post object. %} <picture class="m-hero__image"> <img alt="{{hero.thumbnail.alt}}" role="presentation" src="{{hero.thumbnail.src('hero_full')}}" srcset="{{hero.thumbnail.srcset}}" sizes="{{hero.thumbnail.img_sizes}}"> </picture> |
Admittedly, I find the Twig version to be much quicker and easier to implement thanks to the structure of the Twig\Post object.
But really, the fun part of creating a Responsive image strategy process is deciding exactly how it will best fit into your site’s development process. Answering these questions will always help guide your decision making with regard to responsive image implementation:
This post is short and (hopefully) sweet and there is much more you can learn about implementing responsive images. Below are a couple of my personal favorite sources for additional reading about the techniques I wrote about.
Sign up today to have our latest posts delivered straight to your inbox.