Alistair Shepherd - Front-End Developer
SeriesEight
<img
src="/our-image.jpg"
alt="our image"
>
<img
src="/wp-content/uploads/our-image.jpg"
srcset="
/wp-content/uploads/our-image-300x200.jpg 300w,
/wp-content/uploads/our-image-768x512.jpg 768w,
/wp-content/uploads/our-image-1024x683.jpg 1024w,
/wp-content/uploads/our-image-1536x1024.jpg 1536w
"
sizes="(min-width: 800px) 768px, 100vw"
...
>
Size | |
---|---|
Source JPEG | 300kB |
Optimised JPEG | 60kB |
WebP 🙂 | 36kB |
AVIF * 😀 | 28kB |
JPEG XL * 😍 | 24kB |
Size | Chrome | Firefox | Safari | |
---|---|---|---|---|
Source JPEG | 300kB | yes | yes | yes |
Optimised JPEG | 60kB | yes | yes | yes |
WebP 🙂 | 36kB | yes | yes | recent |
AVIF * 😀 | 28kB | yes | recent | no |
JPEG XL * 😍 | 24kB | no | no | no |
Size | |
---|---|
Source JPEG | 300kB |
Optimised JPEG | 60kB |
WebP 🙂 | 36kB |
AVIF * 😀 | 28kB |
JPEG XL * 😍 | 24kB |
<picture>
<source
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="https://example.com/images/our-image_width1200_quality40.jpg 1200w"
sizes="...">
<img
srcset="https://example.com/images/our-image_width600_quality80.jpg 600w"
sizes="..."
alt="">
</picture>
iPhone 12 Pro (right) screen:
The browser could decide to load an image with resolution 3x larger than it's displayed - 9x increase in file size!!!
We can mitigate increase in file size by increasing the image compression without visible effect.
<img
loading="lazy"
decoding="async"
>
<picture>
<source
type="image/avif"
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="/assets/image/otter-300-q40.avif 300w, /assets/image/otter-450-q40.avif 450w, /assets/image/otter-600-q40.avif 600w,
/assets/image/otter-800-q40.avif 800w, /assets/image/otter-1000-q40.avif 1000w, /assets/image/otter-1200-q40.avif 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<source
type="image/avif"
srcset="/assets/image/otter-300-q80.avif 300w, /assets/image/otter-450-q80.avif 450w, /assets/image/otter-600-q80.avif 600w,
/assets/image/otter-800-q80.avif 800w, /assets/image/otter-1000-q80.avif 1000w, /assets/image/otter-1200-q80.avif 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<source
type="image/webp"
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="/assets/image/otter-300-q40.webp 300w, /assets/image/otter-450-q40.webp 450w, /assets/image/otter-600-q40.webp 600w,
/assets/image/otter-800-q40.webp 800w, /assets/image/otter-1000-q40.webp 1000w, /assets/image/otter-1200-q40.webp 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<source
type="image/webp"
srcset="/assets/image/otter-300-q80.webp 300w, /assets/image/otter-450-q80.webp 450w, /assets/image/otter-600-q80.webp 600w,
/assets/image/otter-800-q80.webp 800w, /assets/image/otter-1000-q80.webp 1000w, /assets/image/otter-1200-q80.webp 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<source
media="(-webkit-min-device-pixel-ratio: 1.5)"
srcset="/assets/image/otter-300-q40.jpg 300w, /assets/image/otter-450-q40.jpg 450w, /assets/image/otter-600-q40.jpg 600w,
/assets/image/otter-800-q40.jpg 800w, /assets/image/otter-1000-q40.jpg 1000w, /assets/image/otter-1200-q40.jpg 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)">
<img
alt="otter standing on a log looking out majestically"
src="/assets/image/otter-1200-q80.jpg"
srcset="/assets/image/otter-300-q80.jpg 300w, /assets/image/otter-450-q80.jpg 450w,
/assets/image/otter-600-q80.jpg 600w, /assets/image/otter-800-q80.jpg 800w,
/assets/image/otter-1000-q80.jpg 1000w, /assets/image/otter-1200-q80.jpg 1200"
sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)"
width="1200"
height="784"
loading="lazy"
decoding="async"
>
</picture>
<?php
add_image_size('image-size-name', 1000, 600, true);
Applies to all images, not just those that need it!
Source and image credit:
HTTP Archive Web Almanac, 2021 - CMS Chapter
and many more
Web Server
HTML
CSS
JS
Images
Images
User's browser
Optimised
Source
Web Server
User's browser
HTML
CSS
JS
Images
Images
Web Server
Optimised
Source
Web Server
User's browser
HTML
CSS
JS
Images
Images
Media Storage
https://example.imagecdn.com
https://example.imagecdn.com
/https://oursite.com
/wp-content/uploads
/example.jpg
https://example.imagecdn.com
/example.jpg
https://example.imagecdn.com
/example.jpg
?w=600&h=400
https://example.imagecdn.com/fetch
/example.jpg
/w_600,h_400
.../w_300,h_600,c_thumb,g_auto/...
Tall banner with automatic gravity
.../w_1000,h_400,c_fill,g_north,
e_colorize:30,co_rgb:dd14d1/...
Wide banner anchored to top, coloured pink
Changing the setting upload_url_path
within database table wp_options
will change the image domain, allowing you to set it to your image cdn
You could also move your uploads to cloud storage which has benefits:
Check out the plugins:
Depending on Image CDN provider there are likely both official and unofficial plugins that make integration very easy and might give lots of bonus features
Image courtesy of Cloudinary WordPress plugin
<?php
echo image( [
'image' => get_field('image'),
'srcset' => [300, 450, 600, 800, 1000, 1200],
'sizes' => '100vw',
'loading' => 'lazy'
'class' => 'image-class'
] );
accud.io/imagecdn-acf
For very high performing sites different origin has an impact
Solution for nginx
location /cdn/ {
proxy_pass https://example.imagecdn.com/;
}
These slides, my sources and helpful links on image CDNs available at accud.io/wordpress-imagecdns
On twitter and most social media @accudio
My website and blog posts alistairshepherd.uk