Let’s first understand why its important for your website to retina-ready nowadays. With the rise of very high density “super retina” displays in the newest high-end devices, capping image fidelity to 2x leads to a big improvement in terms of rendering speed, and no perceivable quality loss for your users.

So the first thing we started doing was to provide both a standard image and an image optimized for Retina displays, using the srcset attribute and the x descriptor. Like this:

<img
    src="image_1x.jpg"
    srcset="
        image_1x.jpg 1x,
        image_2x.jpg 2x,
        image_3x.jpg 3x
    "
    alt="Test Image for Retina"
    width="1920"
    height="600"
/>

See the 1x and 2x? This helps the browser identify which image is the regular version and which is the Retina version. If the user has a Retina device, the browser wills serve the 2x image. If they don’t, it’ll serve the 1x version. And if the browser doesn’t support srcset, then it’ll use the one in the src attribute.

Let’s start adding code to make our website retina-ready.

Step 1: Define Image Sizes

We’re going to use add_image_size wordpress function to define sizes and hook it with after_setup_theme.

add_action( 'after_setup_theme', function(){

	$image_sizes = [
		[
			'size'		=>	'thumbnail',
			'width'		=>	150,
			'height'	=>	150
		],
		[
			'size'		=>	'medium',
			'width'		=>	300,
			'height'	=>	300
		],
		[
			'size'		=>	'medium_large',
			'width'		=>	768,
			'height'	=>	0
		],
		[
			'size'		=>	'large',
			'width'		=>	1024,
			'height'	=>	1024
		]
	];

	foreach( $image_sizes as $sizes ) {
		add_image_size( sprintf('%s', $sizes['size']), $sizes['width'], $sizes['height'] );
		add_image_size( sprintf('%s@%dx', $sizes['size'], 2), $sizes['width']*2, $sizes['height']*2 );
		add_image_size( sprintf('%s@%dx', $sizes['size'], 3), $sizes['width']*3, $sizes['height']*3 );
	}

} );

The above code adding image sizes in following order:

add_image_size( 'thumbnail', 150, 150 );
add_image_size( 'thumbnail@2x', 300, 300 );
add_image_size( 'thumbnail@3x', 450, 450 );
...

If your images already uploaded then make sure to regenerate them.

Step 2: Insert Retina Sizes in SRCSET

We’re going to use wp_get_attachment_image_attributes filter hook, this hook provide us 3 image parameters, array of attribute values $attr, attachment $attachment, and requested size $size.

You can ready more about it in developer resources.

add_filter( 'wp_get_attachment_image_attributes', function( $attr, $attachment, $size ) {

	// Code

	return $attr;
}, 10, 3 );

Here is complete code:

add_filter( 'wp_get_attachment_image_attributes', function( $attr, $attachment, $size ) {

	$img_id			= $attachment->ID;
	$requested_image	= wp_get_attachment_image_src( $img_id, $size );
	$res			= ['2x', '3x'];
	$srcset			= [];
	$size_args       	= [
		'width'		=> $requested_image[1],
		'height'	=> $requested_image[2]
	];

	$srcset[] = $requested_image[0] .' 1x';
	foreach($res as $r) {
		$r_img = $size .'@'. $r;
		$r_src = wp_get_attachment_image_src($img_id, $r_img);
		if($r_src[3] == true) {
			$srcset[] = esc_url($r_src[0]) .' '. $r;
		}
	}

	$attr['src']    = $requested_image[0];
	$attr['srcset'] = implode( ', ', $srcset );
	unset($attr['sizes']);

	return $attr;
}, 10, 3 );

First we define resolutions 2x, 3x in $res variable, then in loop we checked if image size exists $r_src = wp_get_attachment_image_src($img_id, $r_img); if it’s true save them in $srcset[].

After that we used PHP implode() function to convert array into string, then save the $srcset in $attr['srcset'].

Final result will be looks like this:

<img width="300" height="300" src="image-300x300.jpeg" class="wp-post-image" alt="" srcset="image-300x300.jpeg 1x, image-600x600.jpeg 2x, image-900x900 3x">

Let me know if you have any trouble implementing this code in comment section.

Have fun coding!

Categorized in:

WordPress,