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!