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>Source and image credit:
HTTP Archive Web Almanac, 2021 - Media 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/src/assets
/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
<picture>
  <source
      media="(-webkit-min-device-pixel-ratio: 1.5)"
      srcset="
        https://example.imagecdn.com/images/w_300,q_40/otter.jpg 300w,
        https://example.imagecdn.com/images/w_450,q_40/otter.jpg 450w,
        https://example.imagecdn.com/images/w_600,q_40/otter.jpg 600w,
        https://example.imagecdn.com/images/w_800,q_40/otter.jpg 800w,
        https://example.imagecdn.com/images/w_1000,q_40/otter.jpg 1000w,
        https://example.imagecdn.com/images/w_1200,q_40/otter.jpg 1200w"
      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="https://example.imagecdn.com/images/w_800,q_80/otter.jpg"
    srcset="
      https://example.imagecdn.com/images/w_300,q_80/otter.jpg 300w,
      https://example.imagecdn.com/images/w_450,q_80/otter.jpg 450w,
      https://example.imagecdn.com/images/w_600,q_80/otter.jpg 600w,
      https://example.imagecdn.com/images/w_800,q_80/otter.jpg 800w,
      https://example.imagecdn.com/images/w_1000,q_80/otter.jpg 1000w,
      https://example.imagecdn.com/images/w_1200,q_80/otter.jpg 1200w"
    sizes="(min-width: 87rem) 40rem, (min-width: 768px) calc(50vw - 4rem), calc(100vw - 2rem)"
    width="1200"
    height="784"
    loading="lazy"
    decoding="async"
  >
</picture>Cloudinary WordPress plugin
Imagekit.io integrations
<img src="{{ image | img_url: '800x300', crop: 'center' }}" ...>Shopify Image CDN
{% image {
  name: 'otter.jpg'
  alt: 'an otter standing on a log looking majestic'
  srcset: [300, 450, 600, 800, 1000, 1200]
  sizes: '100vw'
  width: 1200
  height: 800
  loading: 'lazy'
  class: 'image-class mb-xl'
} %}accud.io/imagecdn-11ty
import Image from 'components/Image'
export default function () {
  return (
    <Image
      src="otter.jpg"
      alt="an otter standing on a log looking majestic"
      srcset={[300, 450, 600, 800, 1000, 1200]}
      sizes="100vw"
      width="1200"
      height="800"
      loading="lazy"
      className="image-class mb-xl"
    />
  )
}accud.io/imagecdn-react
<?php
echo image([
  'image'   => 'otter.jpg',
  'alt'     => 'an otter standing on a log looking majestic',
  'srcset'  => [300, 450, 600, 800, 1000, 1200],
  'sizes'   => '100vw',
  'width'   => 1200,
  'height'  => 800,
  'loading' => 'lazy',
  'class'   => 'image-class'
]);
accud.io/imagecdn-php
For very high performing sites different origin has an impact
Solutions for nginx and Netlify
location /cdn/ {
  proxy_pass https://example.imagecdn.com/;
}
[[redirects]]
  from = '/cdn/:image'
  to = 'https://example.imagecdn.com/:image'
  status = 200These slides, my sources and helpful links on image CDNs available at accud.io/imagecdns
On twitter and most social media @accudio
My website and blog posts alistairshepherd.uk