Websites today are accessed by a variety of devices with different screen sizes and resolutions. Additionally these devices are often connected via low bandwidth connections.

While CSS and JavaScript can adapt designs to work well on small devices with touch screens, the content is still mostly identical. Users on a mobile phone will have to spend time and money downloading a large image meant for the desktop version, that then gets reduced to a much smaller size on their device.

Higher resolution, or retina screens, have also become a common feature among high end phones, tablets, and laptops. These devices need larger images, to account for their higher screen density. Serving content adapted to these devices was up until recently not possible with plain HTML.

The solution to these problems are responsive images.

Introduction to responsive images

If you’re not familiar with the concept, I’d recommend reading Responsive Images in Practice on A List Apart before continuing.

The implementation in WordPress modifies the markup of image tags embedded in the content. This is done every time a page is generated, by the wp_make_content_images_responsive() function which is hooked to the_content filter.

This function uses regular expressions to find <img> tags in the post content, and modifies the markup to include the new srcset and sizes attributes. This means that new, as well as existing content, benefits from the responsive image markup.

This is the markup generated by WordPress 4.3 for an image embedded in the content:

<img class="alignnone wp-image-1718 size-large"
 src="https://website.com/wp-content/uploads/2015/12/beach-1024x768.jpg"
 alt="beach" width="840" height="630">

This is the output in WordPress 4.4 and later:

<img class="alignnone wp-image-1718 size-large"
 src="https://src.wordpress-develop.dev/wp-content/uploads/2015/12/beach-1024x768.jpg"
 alt="beach" width="840" height="630"
 srcset="http://website.com/wp-content/uploads/2015/12/beach-300x225.jpg 300w,
 http://website.com/wp-content/uploads/2015/12/beach-768x576.jpg 768w,
 http://website.com/wp-content/uploads/2015/12/beach-1024x768.jpg 1024w,
 http://website.com/wp-content/uploads/2015/12/beach-1200x900.jpg 1200w,
 http://website.com/wp-content/uploads/2015/12/beach.jpg 1600w"
 sizes="(max-width: 840px) 100vw, 840px">

As you can see, the responsive markup is a lot more verbose:

  • The srscset attribute contains a list of available image sizes, along with an indication of their width. So for the beach-768x576.jpg image, the width is 768w, 768 pixels wide.
  • The sizes attribute contains indications about what size picture to load depending on the viewport width. So (max-width: 840px) 100vw, 840px means “Is the viewport smaller than 840px? If yes, the picture will be the full width of the viewport. Else it’s going to be a fixed 840px.

The images listed in the srcset attribute correspond to the different sizes that WordPress automatically generates. Version 4.4 introduces a new default intermediate size, medium_large, which has a width of 768px, with no height limit. This helps in filling up the gap between the medium and large sizes.

Template Tag enhancements

The Template Tags API contains a number of functions that output image tags, like for example the_post_thumbnail(). WordPress 4.4 updates all of these functions to include responsive image markup in their output. You can look at the code of wp_get_attachment_image() to get an idea of how WordPress handles this internally.

If you create your own template tags that output image markup, you will have to add srcset and sizes attributes to get responsive images support. WordPress 4.4 introduces the wp_get_attachment_image_srcset() and wp_get_attachment_image_sizes() functions that return the corresponding data for these new HTML attributes.

Handling non-Media images

By the term “non-Media images” I designate images that aren’t handled via WordPress’ Media features. An example would be images that are shipped as part of the theme folder. A common use case in client projects would be a company logo. You would add this image to the theme’s folder, and then include it directly in the template.

In this case, you cannot leverage all the functions presented so far. You would have to generate the various image sizes yourself, and create the correct values for the responsive markup yourself.

Customizing Responsive Images markup

To modify the content of the srcset attributes, you can use the wp_calculate_image_srcset filter. It passes an array of data. Here is an sample element of this array:

[300]=>
 array(3) {
 ["url"]=>
 string(77) "http://website.com/wp-content/uploads/2015/12/beach-300x225.jpg"
 ["descriptor"]=>
 string(1) "w"
 ["value"]=>
 int(300)
 }

The key of each element is the image width. The value is another array with the URL to the image, the descriptor (for the width or display density) as well as the value associated with the descriptor. You can remove, modify, or add elements to this array to customize the srcset output.

To modify the content of the sizes attribute, you can use the wp_calculate_image_sizes filter. It passes the content of that attribute as a string. You can look at Twenty Sixteen to see an example use of this filter.

Another interesting filter to look at is wp_get_attachment_image_attributes. While this filter has been around since version 2.8, the $attr array that passes through the filter got two now additions in 4.4. Here is some sample data:

array(5) {
 ["src"]=>
 string(85) "http://website.com/wp-content/uploads/2015/12/beach-1200x900.jpg"
 ["class"]=>
 string(45) "attachment-post-thumbnail size-post-thumbnail"
 ["alt"]=>
 string(7) "Big Sur"
 ["srcset"]=>
 string(450) "http://website.com/wp-content/uploads/2015/12/beach-300x225.jpg 300w, http://website.com/wp-content/uploads/2015/12/beach-768x576.jpg 768w, http://website.com/wp-content/uploads/2015/12/beach-1024x768.jpg 1024w, http://website.com/wp-content/uploads/2015/12/beach-1200x900.jpg 1200w, http://website.com/wp-content/uploads/2015/12/beach.jpg 1600w"
 ["sizes"]=>
 string(33) "(max-width: 1200px) 100vw, 1200px"
}

Twenty Sixteen uses this filter to modify the output of the_post_thumbnail(). Since the filter passes $size, which contains the name of an image size, you can use this to target all images in the medium size for example.

There’s also a new filter called max_srcset_image_width. This filter allows theme developers to set the largest image width to be included in the srcset attributes. By default, this filter is set to 1600. If you would set it to 500 for example, WordPress would only include images in the the srcset that are equal or smaller in width than 500px.

Responsive Images in themes

WordPress 4.4 has added all the basic tools to really optimize a theme for saving bandwidth on devices width smaller screens. As a theme developer, you have the best knowledge of how to optimize the srcset and sizes attributes to load the smallest image possible to achieve the desired visual result.

In addition, since responsive images can be used to target screen densities, this new feature is the best way forward for making images display great on retina screens.

Further Reading

For more information, you can read Responsive Images in WordPress 4.4 on the Make/Core blog. If you want to know about the topic of responsive images in general, I’d recommend to read Using Responsive Images (Now) on A List Apart.