Improve page speed in WordPress with srcset

Last modified March 12, 2019
.* :☆゚

If you are serving a lot of images on a page, it is important to think about how you’re serving them. You want the images to look good on large screens, but don’t want to be loading in these humungous sizes for smaller screens and mobiles which eats up valuable bandwidth.

If you’re developing themes with WordPress, I’d like to point you to a pretty neat solution that is handled out of the box, and something you can implement fairly easily.

Simply use the wp_get_attachment_image_srcset() function for all your image requirements. Yes, even backgrounds.

The great thing about this function is that you can take advantage of WordPress’ amazing image management to serve appropriately sized images depending on the browser size, and control resized images with ease.


The old way

You may have displayed a feature image like this:

<?php
if ( has_post_thumbnail() ) :
$thumb_id = get_post_thumbnail_id();
$thumb_url_array = wp_get_attachment_image_src($thumb_id, 'large', true);
$thumb_url = $thumb_url_array[0];
$title = get_post($thumb_id)->post_title;
$alt = get_post_meta($thumb_id, '_wp_attachment_image_alt')[0]; ?>

<img src="<?php echo esc_url($thumb_url)?>" alt="<?php esc_attr_e($alt); ?>" title="<?php esc_attr_e($title); ?>">

<?php endif;

or with ACF, like this:

<?php
$image = get_field('feature');
$size = 'large';
$thumb = $image['sizes'][$size];
$title = $image['title'];
$alt = $image['alt'] ? $image['alt'] : $title;
?>

<img src="<?php echo esc_url($thumb); ?>" alt="<?php esc_attr_e($alt); ?>">

Or even like this!

 <?php echo get_the_post_thumbnail( get_the_ID(), 'medium' );?>

Notice these functions generate an image tag with just one image.


The newer, more user-friendly way

Use the srcset function! FOR EVERYTHING 😁

<?php
$img_id = get_post_thumbnail_id();
$size = 'large';
$img_src = wp_get_attachment_image_url( $img_id, $size );
$img_srcset = wp_get_attachment_image_srcset( $img_id, $size );
$title = get_post($id)->post_title;
$alt = isset(get_post_meta($id, '_wp_attachment_image_alt')[0]) ? get_post_meta($id, '_wp_attachment_image_alt')[0] : $title;
$caption = wp_get_attachment_caption($img_id);
?>
<figure class="imge-wrapper">
<img src="<?php echo esc_url( $img_src ); ?>"
srcset="<?php echo esc_attr( $img_srcset ); ?>"
sizes="
(max-width: 768px) 800px,
(max-width: 1200px) 1400px,
(max-width: 2000px) 2000px"
alt="<?php echo $alt; ?>"
class="img"
loading="lazy">
<figcaption><?php echo $caption;?></figcaption>
</figure>

Note that WordPress does have a function that can generate all of this markup for you automatically, using wp_get_attachment_image(). I personally like to construct the markup myself however so I have total control over the markup where I can add/change ids, classes, and data attributes easily.

The only thing you need to provide this snippet is the image attachment ID. The snippet will then retrieve both the img src and the srcset using the wp_get_attachment_image_url() and wp_get_attachment_image_srcset() functions. Notice how the image tag now has a sizes attribute? That’s where you put all your media queries depending on how you want the image to resize.

For example:

sizes="(max-width: 320px) 350px,
        (max-width: 768px) 500px,
        (max-width: 1200px) 800px,
        100vw"

Using srcset in WordPress makes uses of it’s generated image thumbnails. The default thumbnail sizes are:

<?php 
the_post_thumbnail('thumbnail');       // Thumbnail (default 150px x 150px max)
the_post_thumbnail('medium');          // Medium resolution (default 300px x 300px max)
the_post_thumbnail('medium_large');    // Medium Large resolution (default 768px x 0px max)
the_post_thumbnail('large');           // Large resolution (default 1024px x 1024px max)
the_post_thumbnail('full');            // Original image resolution (unmodified)

Wordpress’ preset image thumbnails have gone the extra mile for me in almost all my web projects- I’ve never had to set custom thumbnail sizes in functions.php, and I personally think excess image generation can be overkill in most cases. I will however often change the image thumbnail sizes in Settings > Media especially if I need large full-width sized images. My tweaks to the default sizes are usually:

  • thumbnail: 150 x 150 max
  • medium: 500 x 500 max
  • large: 1600 x 1200 max

My policy is to never load in an image larger than 3000px wide because when you get past this size, the size of images often blow up and it’s just not worth the extra kB.

Handy tip: WordPress also generates a 'medium_large' thumbnail even though it is not explicitly shown in the visual interface. By default it is tablet size(768px wide) and I've actually found it super handy in many cases. For more in depth info, I suggest reading up on the [codex](https://codex.wordpress.org/Post_Thumbnails#Thumbnail_Sizes).

With the srcset function there really is no need to use the_post_thumbnail() at all in my opinion. I often use srcset in place of background images, using the object-fit: cover CSS property to make sure the image is cropped or contained like a background would be.

Just be aware IE11 does not support object-fit, so if you must support it in your project I suggest using single src images only or using a polyfill.