• Stars
    star
    412
  • Rank 105,024 (Top 3 %)
  • Language
  • License
    MIT License
  • Created over 2 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Repository to collect best practices for web images ๐Ÿž

Best practices for images

Repository to collect best practices for web images

Responsive images

With media

We can use media to define a media query as a breakpoint to load a responsive image.

<picture>
  <source srcset="image-ultrawide.jpg" media="(min-width: 1200px)">
  <source srcset="image-wide.jpg" media="(min-width: 600px)">
  <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  <img src="image.jpg" height="300" width="200" alt="Awesome image">
</picture>

In the above code, the browser loads the image.jpg in mobile version, the image-wide.jpg in tablets resolutions or bigger, and the image-ultrawide.jpg will be loaded in screen resolutions bigger than 1200px. NOTE: Browser finds the first matching condition and ignores everything after.

With sizes

We can use sizes, that allows you to specify the layout width of the image for a list of media conditions.

<img 
  srcset="image-wide.jpg 600w,
          image-ultrawide.jpg 1200w"
  sizes="(min-width: 600px) 600w,
         (min-width: 1200px) 1200w"
  src="image.jpg" height="300" width="200" alt="Awesome image">

In the above code (like with media), the browser loads the image.jpg in mobile version, the image-wide.jpg in tablets resolutions or bigger, and the image-ultrawide.jpg will be loaded in screen resolutions bigger than 1200px.

Serve modern image formats

Usually, the next-gen image formats like WebP, AVIF or JPEG XL, can optimize image weight while maintaining good image quality.

With the HTML tag <picture> we can specify the type in the <source> tag. The type is the image format, and we can use it to serve modern image formats. The browser will use the first image format that it supports.

<picture>
  <source type="image/webp" srcset="image.webp">
  <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  <img src="image.jpg" height="300" width="200" alt="Awesome image">
</picture>

In the above code, the browser loads the first image format that it can render. E.g. Internet Explorer 11 nor Safari 13 can't load the WebP image format (a next-gen image format), so they will load the JPEG image.

<picture>
  <source type="image/jxl" srcset="image.jxl">
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  <img src="image.jpg" height="300" width="200" alt="Awesome image">
</picture>

In the above code, we list all the modern image formats, from "more optimized" to "less optimized". The browser will show the first image that it can load and render.

Serve responsive and modern image formats

We can combine both approaches to serve modern image formats and responsive images to load the best image on each device.

<picture>
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.jxl 600w,
            image-ultrawide.jxl 1200w"
    type="image/jxl">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.avif 600w,
            image-ultrawide.avif 1200w"
    type="image/avif">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.webp 600w,
            image-ultrawide.webp 1200w"
    type="image/webp">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.jpg 600w,
            image-ultrawide.jpg 1200w"
    type="image/jpeg">
  <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  <img src="image.jpg" height="300" width="200" alt="Awesome image">
</picture>

In the above code, we have a combination of all modern image formats and the sizes needed. This is an example, as every site or project needs different sizes.

Improve the Web Performance

We can use several attributes to improve the Web Performance, aka user experience.

  • loading provides a hint to the user agent on how to handle the loading of the image which is currently outside the window's visual viewport. We can set it to eager (default value) which tells the browser to load the image as soon as the <img> element is processed, or lazy that tells the user agent to hold off on loading the image until the browser estimates that it will be needed imminently.
  • decoding represents a hint given to the browser on how it should decode the image. The values are sync to decode the image synchronously for atomic presentation with other content, async to decode the image asynchronously and reduce delay in presenting other content, and auto (default mode) which indicates no preference for the decoding mode. The browser decides what is best for the user.
  • fetchpriority represents a hint given to the browser on how it should prioritize the fetching of the image relative to other resources. The values are high to fetch the image at a high priority relative to other images, low to fetch the image at a low priority relative to other images, and auto (default mode) which indicates no preference for the fetch priority. The browser decides what is best for the user. By default images are initially low, until the browser has done layout and knows what images are in the viewport. These are then boosted to high priority. You can make this boost happen earlier for an important image (e.g. LCP image) you know has a high probability of being in the viewport by using fetchpriority="high". Similarly you can deprioritize less important images that are technically in the viewport, but not viewable (e.g. second and third carousel images) by using fetchpriority="low". Typically you would not need to use fetchpriority on off-screen images as the browser default (low until in viewport) is optimal there.

Now we will use this attributes to improve the user experience of our images

<picture>
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.jpg 600w,
            image-ultrawide.jpg 1200w"
    type="image/jxl">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.avif 600w,
            image-ultrawide.avif 1200w"
    type="image/avif">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.webp 600w,
            image-ultrawide.webp 1200w"
    type="image/webp">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.jpg 600w,
            image-ultrawide.jpg 1200w"
    type="image/jpeg">
  <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  <img 
    loading="lazy"
    decoding="async"
    src="image.jpg"
    height="300"
    width="200"
    alt="Awesome image">
</picture>

In the above code, we have a better code for all the images below the fold (outside the viewport) and the browser does not load these images (according to the threshold)

Improve the image detected as LCP element of the Core Web Vitals

The previous code covers the scenario for all images outside of the viewport. Usually, the LCP metric refers to an image element, so we can iterate to improve it.

<picture>
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.jpg 600w,
            image-ultrawide.jpg 1200w"
    type="image/jxl">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.avif 600w,
            image-ultrawide.avif 1200w"
    type="image/avif">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.webp 600w,
            image-ultrawide.webp 1200w"
    type="image/webp">
  <source
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="image-wide.jpg 600w,
            image-ultrawide.jpg 1200w"
    type="image/jpeg">
  <!-- The <img> tag is a fallback image (required in the <picture> tag) -->
  <img 
    fetchpriority="high"
    decoding="sync"
    src="image.jpg"
    height="300"
    width="200"
    alt="Awesome image">
</picture>

In the above code, we changed the attribute decoding to sync to priorize the decoding, removed the attribute loading because the default behavior is eager, so we don't need it, and we add the attribute fetchpriority="high" to indicate to the browser to load the image as soon as possible.

By the way, we don't need to add these attributes to all <source> tags, only to <img> tags.

If an image is not immediately discoverable in the HTML, a preload link tag, with fetchpriority="high" to boost the priority, can also allow it to be loaded as soon as possible. See Optimize when the resource is discovered #

Use a CDN Image Service

We see that we need a lot of code to deliver the best user experience ๐Ÿ™ˆ.

We can use a CDN Image Service like Cloudinary to remove the part of code that references the image format, as these services serve the best image format supported by the browser.

The browser sends in the HTTP Headers the accept header value to indicate which content types, expressed as MIME types.

Accept Header

In the screenshot above we see that my current version browser supports image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;, so with a service of automatic image format, the service will send me an avif image format in response.

<picture>
  <img 
    sizes="(min-width: 600px) 100vw, 600px,
           (min-width: 1200px) 100vw, 1200px"
    srcset="
      https://res.cloudinary.com/nucliweb/image/upload/c_scale,f_auto,w_600/v1010101010/demo/image.png 600px,
      https://res.cloudinary.com/nucliweb/image/upload/c_scale,f_auto,w_1200/v1010101010/demo/image.png 1200px"
    src="https://res.cloudinary.com/nucliweb/image/upload/f_auto/v1010101010/demo/image.png"
    loading="lazy"
    decoding="async"
    height="300"
    width="200"
    alt="Awesome image">
</picture>

Now we don't need to define the type because this is transparent to us. The service sends the best image format supported by the browser. Notice that the image in the samples is an PNG image, yet the browser will load an avif image format.


Acknowledgement

  • Addy Osmani, for this image and for all the tips that he are sharing with the community.

More Repositories

1

webperf-snippets

โšก๏ธ ๐Ÿ’พ Web Performance Snippets
MDX
1,333
star
2

People-You-Should-Follow-on-CodePen

People You Should Follow on CodePen
JavaScript
658
star
3

avif-in-css

PostCSS plugin to use AVIF in CSS background
JavaScript
43
star
4

postcss-magic-animations

PostCSS plugin that adds @keyframes from Magic Animations | v0.3.0
JavaScript
41
star
5

my-terminal

My terminal config
22
star
6

People-You-Should-Follow-on-Open-Processing

People You Should Follow on https://www.openprocessing.org/
19
star
7

image-optimization-workshop

Image Optimization Workshop
HTML
15
star
8

Komenco

Komenco es un starter kit, boilerplate o template que sirve para comenzar a desarrollar un proyecto web
CSS
12
star
9

backlog

Backlog de contenidos para el blog, canal de YouTube y directos en Twitch.
11
star
10

MDNSearchDoc

Sublime Text MDN Search Doc
JavaScript
10
star
11

flexbox

Ejemplos de las propiedades de Flexbox
JavaScript
10
star
12

cavif-bin

cavif bin-wrapper that makes it seamlessly available as a local dependency
JavaScript
8
star
13

Creative-Coding-T3chFest-2019

Demo Creative Coding T3chFest
JavaScript
7
star
14

nucliweb-image-optimization

JavaScript
6
star
15

houdini

CSS Houdini samples
HTML
5
star
16

AnimacionesCSS-EscuelaIT

Ejercicios del curso Animaciones CSS en Escuela IT
CSS
5
star
17

image-perf

Image Perf is a tool to optimize the images
5
star
18

webperf-tools

Web Performance Command Line Tools
4
star
19

atom-mdn-doc

Atom MDN Doc is a package allows you to consult the documentation in the Mozilla Developer Network
JavaScript
4
star
20

extract-critical-css

Extract Critical CSS
JavaScript
3
star
21

jxl-in-css

PostCSS plugin to use JXL in CSS background
JavaScript
3
star
22

imagemin-avif

AVIF plugin for imagemin
3
star
23

responsive-images-squoosh

Generate responsive images and next-gen image formats with squoosh-cli
JavaScript
3
star
24

Brackets.mdn-search-doc

Brackets Extension for consult the documentation in the Mozilla Developer Network
JavaScript
3
star
25

workshop-flexbox

Workshop Flexbox
JavaScript
2
star
26

lighthouse-gh-action

JavaScript
2
star
27

must-development-talks

Filtered Frontend and Backend talks to watch
2
star
28

lhci-testing

SCSS
2
star
29

nucliweb.net

JavaScript
2
star
30

web-performance-workshop-HooBank-site

web-performance-workshop-HooBank-site
JavaScript
2
star
31

Brackets.SnapSVG-Doc

JavaScript
2
star
32

pysfoc-api

People You Should Follow on CodePen API
JavaScript
1
star
33

playwright-workshop

JavaScript
1
star
34

nucliweb

1
star
35

cypress-workshop

cypress-workshop
JavaScript
1
star
36

csscommunitydev-logo

CSS Community Dev Logo
JavaScript
1
star
37

nextjs-netlify-blog-template

TypeScript
1
star
38

optim-images-bot

HTML
1
star
39

react-performance

JavaScript
1
star
40

frontflix

Listado de charlas frontend
1
star
41

Workshop-SVG

SVG Workshop at Schibsted Spain
1
star
42

lh-gh-action

CSS
1
star
43

avif-in-css-demo

AVIF in CSS demo site
JavaScript
1
star
44

lcp-image-benchmark

JavaScript
1
star
45

web-performance-workshop-HooBank-webPerf

web-performance-workshop-HooBank-webPerf
JavaScript
1
star
46

github-slideshow

A robot powered training repository ๐Ÿค–
HTML
1
star
47

webperf-snippets-extension

TypeScript
1
star