WordPress Plus srcset lead banner image

Understanding and extending WordPress’ srcset functions

It’s taken me a long time to feel as though I understand WordPress’ core implementation of srcset. Maybe one could attribute the length of time necessary for comprehension to my lack of programmer brain skills. That could be.

Whatever the reason, I’m happy I understand it now and feel like I have a better handle on functional programming because of it.

My setup: theme and plugins

Helpful resources and WordPress’ own documentation

Some articles about srcset really helped steer me in the right direction in terms of conceptually wrapping my head around how it’s used.

Methodology: image ratios versus image width

For a while, I wrestled with trying to override WordPress’ own srcset sizes with my own. Rather, I distracted myself trying to understand what sizes/ratios they were using them and why my custom sizes weren’t overriding them.

I figured using a 16:9 ratio for all source images, then adding an array of specific sizes within the 16:9 ratio would work. It does work, but it’s too specific and I found that rather problematic. I went researching for image ratio methodology and advice.

There are so many articles about WordPress’ use of srcset but none effectively tackle or give advice on practical image ratios. My advice on this is to start with what you can realistically handle. Meaning, asking yourself how you prepare your images. If you use Photoshop to manually craft lead/featured images and custom image fields, then it might not make sense to make WordPress adhere to those specific dimensions. The crux of srcset is ratios. The browser will only receive the same srcset ratio of sized images that match the ratio of the originally uploaded image. What’s really neat is that you can also simply define an image width and those widths will all get added to the srcset array, which the browser then uses to choose the appropriately sized image to render, given the user’s device resolution. Granted, this is achieved with a bit of help. More on that below in a helper function.

A powerful obstacle: ACF plugin

What’s more than understanding WordPress’ implementation and image ratios, was understanding how to extend its power to the custom fields I’ve created using the Advanced Custom Fields Plugin for WordPress.

By default, ACF doesn’t support srcset properties for custom images. So there are several options ahead to overcome this obstacle. For a while I used WordPress’ get_thumbnail('size'); function for all featured images. Then I simply referenced the largest size I needed for ACF image fields, using the array return value. Then in some templates, I used a slight variation on returning the image values I wanted. The point here is that it all felt too inconsistent. There had to be a better and saner way! And there is!

After lots of trial-and-error, I have drawn the following conclusions and present each as advice for anyone struggling with srcset in WordPress.

Definition: making your own srcset image sizes

I finally landed on defining image sizes by width, only. I know that I can control the ratio in whatever computer application I’m using to generate the images. It’s redundant to impose the same ratio limitations within my CMS. This was the biggest revelation to me. I spent hours wrestling with different aspect ratios, defining them and regenerating all my website’s images.

By defining the widths only you have all the power and leverage all the reusable greatness.

My custom image sizes

// custom image sizes
if ( function_exists( 'add_theme_support' ) ) {
  add_theme_support( 'post-thumbnails' );
  set_post_thumbnail_size( 1800, 9999 );

  // additional image sizes

  add_image_size( 'teaser-square', 300, 300, true);
  //300 square pixels cropped
  
  add_image_size( 'teaser-square-medium', 600, 600, true); 
  //600 square pixels cropped
  
  add_image_size( 'teaser-square-x-large', 800, 800, true);
  //800 square pixels cropped

  // width-only images

  add_image_size( 'three-fourty', 340);
  add_image_size( 'four-twenty', 420);
  add_image_size( 'six-hundred', 600);
  add_image_size( 'seven-sixty', 760);
  add_image_size( 'seven-eighty', 780);
  add_image_size( 'eight-eighty', 880);
  add_image_size( 'ten-eighty', 1080);
  add_image_size( 'twelve-sixty', 1260);
  add_image_size( 'fourteen-hundred', 1400);
  add_image_size( 'eighteen-eighty', 1880);
}

With this setup, I have the freedom to easily reuse all these sizes instead of making them too specific to pieces of content. Having specific ratios may also impose more structure than necessary, too. Again, this is coming from someone who prepares their images prior to uploading them.

Methodology: custom responsive image helper function

//
// Responsive Image Helper Function for ACF
// 
// @param string $image_id the id of the image (from ACF)
// @param string $image_size the size of the thumbnail image or custom image size
// @param string $max_width the max width this image will be shown to build the sizes attribute
//
function grangler_responsive_image($image_id,$image_size,$max_width){
	// check the image ID is not blank
	if($image_id != '') {
	
        // set the default src image size
	$image_src = wp_get_attachment_image_url( $image_id, $image_size );
	// set the srcset with various image sizes
	$image_srcset = wp_get_attachment_image_srcset( $image_id, $image_size );
	// generate the markup for the responsive image
	echo 'src="'.$image_src.'" srcset="'.$image_srcset.'" sizes="(max-width: '.$max_width.') 100vw, '.$max_width.'"';
   }
}

Which I use in my templates in the following way.

Declare variables

<?php
/**
 * The template part for displaying content teaser
 *
 * @package WordPress
 * @subpackage Twenty_Sixteen
 * @since Twenty Sixteen 1.0
 */
 // get the featured image by defining some variables to print below.
   $featured_image = get_post_thumbnail_id();
   $featured_image_size = 'twelve-sixty'; // Set to custom size set in functions.php
   $featured_image_alt = get_post_meta($featured_image, '_wp_attachment_image_alt', true);
?>

I place my variables, when possible, at the top of each template file, that they’re used in. This brings me comfort in easily scanning the file and getting a quick overview of what I’m doing.

Call the function in your template, passing in the image variables

// print the featured_image variable if it isn't empty.
<?php if( !empty($featured_image) ): ?>
  <span class="post-thumbnail">
    <figure <?php post_class('featured-image');?>>
       <img <?php grangler_responsive_image($featured_image, $featured_image_size,'1260px'); ?><?php echo 'alt="' . $featured_image_alt . '"';?> />
    </figure>
  </span>
<?php endif; ?>

This helper function has served me well. Massive thank you to Aaron Rutley for sharing his helper function. Without it this would’ve taken me longer to figure out.

Conclusions

In conjunction with caching and decent lossless image optimization, srcset can help make your site more performant. I’m excited to push this further, as there may be room for less repetition. The line of how much is too much abstraction is another topic entirely.

I’d love to know if anyone has a better approach than where I’ve landed. Let me know if you’ve had your own srcset or image-related performant revelations, in the comments below.