How to (Learn to) Implement Images on the Web (2021)

Ingvild Forseth
14 min readMay 26, 2021

Images are the biggest assets that gets shipped with a web page according to these smarty pants (developer advocates for Google Chrome, my heros ❤), see the quote below.

50% of the bytes that go over the wire for any given page are on average images [from studies across web pages, as of 2020]— Suma

As a frontend developer, you should learn the tricks on how to make images impact the users’ bandwidth as little as possible and the user experience as much as possible. It’s the polite thing do, right?

However, there is a jungle out there. A jungle of internet resources on how to do things, on image formats, and which image formats are outdated and which are new? And even — which of the new ones should actually not be used? Puh!

So I hope I can be your Bagheera on this journey, showing you the way. In this article, I summarize the resources that helped me feel up to speed and knowledgeable on the subject. The article ends with a conclusion on the top greatest tips for images on the web.

Let’s go on a “images on the web” journey. (Source: https://www.moviehousememories.com/the-jungle-book-1967-summary/)

Understand The Different Image Formats

The first thing you should do, is to understand the different image formats. Different image formats are suited for different kind of images. For this purpose, I’ll direct you to the same video as above, the “Image Compression Deep Dive” video from Google Chrome developer advocates Jake Archibald and Surma.

Here are the key point (whenever you are in the need for a quick look-up of the video, without having to see it all over again):

  • Usually, images used on the web have not compressed. For random images on the web, you are usually able to half the size of the image file without losing much of the visual fidelity by re-compressing it. (Jake Archibald 01:05)
  • In a compression process, you are left to decide between different formats, different encoders, and you can also decide the settings within a particular encoder (the last one requires taking the level of expertise up a notch 😊). However, often people don’t optimize their images at all, so a huge performance gain can usually be achieved by just using default settings of an encoder and without going deep into the settings of encoders.
  • Below is the overview over the different the image formats categorized, and what each format spend their bytes on/are not good at. Each category offers a multitude of codecs, and you can try them all out in the Squoosh app that Jake Archibald and his team made.
A categorization of the image formats by Google developers. Source: https://youtu.be/F1kYBnY6mwg?t=127 at 02:07.
The properties of an image you should consider when choosing image format when compressiong to keep the image size as small as possible. Source: https://youtu.be/F1kYBnY6mwg?t=250 at 04:10)
  • If you don’t know which category your image falls into, try different codecs using the Squoosh app (build by Jake Archibald and his team), and use your own eyes to evaluate which codec gives you the best result for the least amount of data.
  • Lossy codecs:
    They use chroma sub sampling, which is to describe the image using brightness (luma) and two chroma/color changes to describe the image, in order to reduce the image size.
    They also take advange of the fact that out human eyes are bad at detecting changes in high frequency, but good at detecting low frequency changes. They divide the image in 8px times 8px blocks, and instead of describing each of the pixels within each block, they describe each block as a set of frequencies. The details of this is definitely out of scope of this article, but Jake illustrates how this work at 10:10 in this video, if you are curious.
A visual representation of the frequencies used by lossy codecs (such as JPEG) to reconstruct shapes in an image. (Source)
  • Lossy image formats are not good at sharp lines with solid colors next to solid color.
  • About lossy codecs (at 12:40 in the video): WebP is better than JPEG. Reasons: It can use a different size for the square when splitting the image up in blocks it will then compress, it can use a nearby square as the starting point for the next, and it can choose between 4 different mathematical conversions for each block, whereas JPEG can only use one. WebP also supports transparency, and in fact has a lossless codec too. But, the downside is, it is not supported in Safari.
  • More about lossy codecs: From 14:20 approximately in the video, Jake shows how to use the Squoosh.app to compress images (because it ): He goes through some advanced settings for the WebP encoder (the alpha filter and the spatial noise shaping), compares WebP to JPEG, and argues that the compressors included in Squoosh are much better than the ones Photoshop offer.
  • About lossless images: Each pixel will be described by the difference to the surrounding pixels. But lossless encoders take more encoding time, because they have to iterate through which strategies at what point in the picture gives the smallest image. Again, the lossless WebP is the best, but it does not have Safari support, but PNG does.
  • About lossless codecs: Again, at around (24:00) in the video, Jake shows how to use the Squoosh app for lossless compression.

But, AVIF is Coming/Is Here Already

In September 2020, Jake Archibald wrote this blog post, acknowledging that the content of the image compression video above now was already outdated, because of the arrival of the new future image format AVIF. (Words of disclamation: I included above the video despite of this, as I believe it is important anyhow to understand the basics, which I think the “image compression deep dive” video above gives.)

Just read the Jake Archibald post on AVIF and get “wowed”. Here at the key takeaway points:

  • AVIF is only supported by Chrome (from v85 and above), but you can use the <picture> tag to provide the client with a fallback. On caniuse.com you can keep track of when other browsers have gained to support for AVIF.
  • Pictures with both low and high frequency details: An acceptable AVIF image (in Jake’s opinion) is half the size of WebP, which again is half the size of JPEG (in total one fourth of the JPEG size then).
  • Flat illustrations (sharp edges, lots of solid colors): SVG off course is the natural choice here, and nonetheless, one would usually go for a lossless codec for these kind of images (to avoid destroying the edges, a high frequency detail). However, it is worth noting that the AVIF image makes a very decent job, 8.69kB compared to 16.3kB of the lossless PNG format (the traced SVG format ended up at 12.5kB), so it made Jake reconsider the kinds of images lossy codecs can be used to.
  • Heavy SVG images: Original SVG started at 82kB, then the optimized PNG ended up at 30kB. There are a number of shapes and filters involved in the picture (which takes a lot of the CPU to render), and that is why it is best to avoid the original SVG. AVIF performs the best her, lowering it to a 13kB image size, a reduction of more than 80%.
  • Illustration with gradients: Flat color and sharp lines usually points to a lossless compression as already discussed in bullet point 3. But, lossless formats usually struggle with gradients, so this is a tricky image to know what to expect. With some extra tweaking on the different codecs (disabling “chroma subsampling for the JPEG and AVI, choosing a “sharp YUV for the lossy WebP, read more about it in Jake’s article, section “Illustration with gradients”), he ends up with AVIF performing the best at 12kB (although some blurring, and changes to some shapes), but it is nearly half the size of the second best codec, which is the lossy WebP at 27kB.
  • Downside of the AVIF format: JPEG and WebP are able to render bits of pieces of the image (either in “passes” like JPEG, or from top to bottom, like WebP) so the users will se the progress of a slow image download, whereas the AVIF image either shows all or nothing. This makes AVIF most appropriate for smaller quick to load-images. (This can however be solved by the format if it would serve a lower quality “preview” version of the image at the start of the file.)
  • Encoding time is a thing when choosing codec. The AVIF format has an “effort” setting in the Squoosh app that you can tweak for the AVIF format, with an encoding time of a couple of seconds on “effort 2”, but it can take up to 10 minutes to encode on effort level 10!
The Squoosh app has an effort level you can experiment with when compressing your image using the AVIF format.
  • Image formats to come: JPEG-XL and WebPv2. Jake is trying to take the claims about JPEG-CL with a pinch of salt as he writes, it will come with a lossless and a lossy compression. The lossless compression it will offer seems to be better the the WebPs at least, but the lossy compression is meant for high quality images (in the cases where you can expect the user to zoom into the images etc.), so it might not be able to compete with the AVIF format at the lossy compression. Details about the WebPv2 codec is yet to come.

Learn To Compress Images

What is “good” enough quality when you compress your images? You don’t want to provide your users with “blocky” images where artifacts of the image have been warped due to the compression as the expense of a smaller image size. There is a fine line there that needs to be figured out, and here is how.

Again, I will refer you to the “Avif has landed” article by Jake Archibald. Here is his rule for “acceptable quality” for the majority of images on the web:

If a user looks at the image in the context of the page, and it strikes them as ugly due to compression, then that level of compression is not acceptable. But, one tiny notch above that boundary is fine. — Jake Archibald

The technique he us used in the article is the following:

  1. He used the Squoosh app.
  2. Zoomed the image out to 50%, to optimize for high-density displays, in which a CSS pixel/software pixel would contain several hardware pixels, e.g. 4 for a 4k display (read more about that for instance here).
  3. Used his human eyes for reference: Dragged the quality slider for the specific format down until it looked bad, then moved it back a little bit.
    If the codec had an “effort” setting, he sat it to max (requires more encoding time though).

Surely, manually compressing every images on you page is not a scalable process. If you need to automate the process, you can use this manual process to figure out the codec settings a couple representative images. Maybe add a bit of extra quality to be safe as Jake points out in his article, and then use those settings in the automation process. Also, surely, for people who really knows a lot about image compression and quality, this way of doing it would not suffice — but we are just interested in doing images on the web a little better :)

Learn To Measure Web Page Performance

Jake Archibald has a great article where he investigates the performance of different websites, in which he also loosely sums up his methodology for measuring a web page’s performance in the section here.

He will use the Chrome DevTools Performance panel during development to measure performance. Then, in production, one can use the web page WebPageTest to test it on low-end devices, as this is what the majority of people actually has.

In the article, he decided to test on a 5 year old phone (Moto G4) on a 3G connection, as he argues that a lot of people don’t want to or can’t afford a high-end phone. So to sum it up, you have to know your users and decide on what you think is a representative device for most of your users, and also where they typically would access your page, in order to decide the quality of internet connection.

The WebPageTest tool gives you measures like: How many seconds it takes the page to become interactive on the first load, and on the second load, and an overview on the order of the downloaded assets and how much time each of them took to download. You even get to see bits used for connection setup (so you can ensure you don’t pay the price of connection setup more than necessary), and also when the actual bytes of each asset is received and hence, claims the bandwidth of the user’s connection.

This overview is interesting to us in this regard (optimizing images on the web), because you make sure that any image are not downloaded before any more critical resources (like the CSS, which actually was the case for the Alpha Tauri webpage he first investigated, using an img tag, and not a link tag, will prevent this), and maybe more important, in the overview you get to see the true download time of each image. In Jake’s experiment, he was able to reduce the image size of both the logo and the hero image by 90% by compression (using the Squoosh app), and that leads to performance gains.

Also, a small tip at the end that also favors to the img tag: Inline SVG should be avoided, as it makes the size of the HTML and hence the time it takes to download, bigger. It also prevents the browser from downloading more critical assets (like the CSS), as the browser downloads the complete HTML before starting on the next thing to download in the markup. For instance, in the case of the first web page he investigates, the browser ends up using bandwidth on a logo that is on the bottom of the page, instead of starting on the css that will style what is about the fold. By using the <img> tag, you allow the browser to be smarter than this about its priorities.

Learn To Use the Sizes Attribute

Do yourself a favor and invest in the “Image Performance” ebook (or print) by Mat Marquis and make it your encyclopedia for the responsive images standard on the web.

Mat Marquis was at the time the chair of the Responsive Issues Community Group (RICG). In the book, he explains how the group developed what is now the new responsive images standard on the web.

The book is from 2018, and he explains the topics and the process of work the group did in a quirky and funny way. Also, the book is only about 70 pages long, so you get a lot of knowledge for your time and your bucks.

First, he makes the case why images do damage due to their great file size. The first chapter is about image formats and compression (a nice way to learn about image formats in addition to the Google video discussed above). The second chapter is about responsive images.

It is mainly the implementation details in chapter two that I want you to take as the take away message from this book. According to Mat, “the term “responsive images” refers to any combinations of the following” (Mat Marquis. “Image Performance”. Apple Books. 2018):

  • Art directions: “requesting visually distinct source files at specific viewport sizes.”
  • Image types: “requesting new image formats with responsible fallbacks.”
  • Display density: “requesting image sources appropriate for high-density displays only when necessary.”
  • Flexible images: “providing the browser with information about a set of image sources and how they’ll be used in a page’s layout, so it can make the most appropriate request for a user’s browsing context.”

(Mat Marquis. “Image Performance”. Apple Books. 2018)

In the book, you learn how to account for all of them. All of the 4 use cases above can be solved with either the <picture> tag and/or the sizes attribute on the <img> tag (which is the result of the work the RICG did). Here follows some examples, which I believe sum up what I regard as the take away messages from the book:

  • Use the picture tag to vary between alternatives of different screen sizes, for example serve a square full width image on a tablet, and a portrait on desktop, or to serve different image formats. Se the examples from Mat Marquis book below ⬇️
The <picture> tag lets you explicitly control which image is rendered on different screen sizes. It can be used to vary between different alternatives for an image to comply to different art directions, for example a square full width image on a tablet in portrait mode, and a different one when the tablet is in landscape mode. Image from: Mat Marquis. “Image Performance”. Apple Books. 2018.
Use the <picture> tag to serve different image formats. In that way, you provide the browsers that support it images in the latest and best formats, at the same time as you provide a fallback image in the browsers that don’t. Image from: Mat Marquis. “Image Performance”. Apple Books. 2018.
  • Use the sizes attribute together with the srcSet attribute to tell the browser what image to render for different screen sizes to make sure you don’t download a bigger image than necessary.
    In the sizes attribute, you write the expected image size for different screen sizes. In the example below, the value of the sizes attribute can be read as follows: If the screen width is minimum 1200px large, the image will be 1200px. If the screen is less (than 1200px), it will be 100% of the viewport.
    In the srcSet attribute, you write what kind of file should be downloaded for the different image sizes. The w represents the real width of the image, which can be found if you inspect the image file on your computer. Thus, the srcSet attribute in the example below can be read like this: If the width of the the image to be displayed is supposed to be less than 400px, download and show the small.jpg file. If the width of the image to be shown should be between 400px and 800px, serve the medium.jpg file. It the width of the image should be between 800px and 1600px, show the large.jpg file, and if the width of the image to be rendered should be between 1600px and 2400px, show the x-large.jpg-file.
By using the sizes attribute on the image tag, you inform the browser how much big the image is expected to be on your page. Through the srcSet attribute, you explicitly tell the browser which image to download for the different sizes/widths that the image is expected to fit in to. By leveraging these two attributes, you can make sure that the browser does not download an image that is bigger than necessary, and you will save the impact the images have on your users´ bandwidth when accessing your page (and overall reducing the total download time for your page). Image from: Mat Marquis. “Image Performance”. Apple Books. 2018.
  • Also, remember this: If using min-width as the media query, you want the largest sources first, as the <picture> tag will chose the first source that passes the media query. If using max-width as the media query, it is the other way around, the smallest image first.

The bullet points above are meant as just a quick reminder whenever necessary. A more extensive explanation about the subject can be found in the Responsive images article on MDN, and specifically, more on how to read the sizes and the srcSet attribute can be found in the Resolution Switching section in that article.

Conclusion

So, to conclude, here are my tips on how to get confident on providing images on the Web:

  • Understand the different image formats and what kind of images they perform best at (lossless and lossy codecs, and image types like photographs vs. illustrations with or without gradients).
  • Compress your images.
  • If you want to me really want to step up your game: Use the <picture> tag to provide images compressed in the AVIF image format in the browsers that support AVIF (because AVIF usually provides the smallest image sizes at an “acceptable” quality), and an other image format in the browsers that don’t support AVIF.
  • Measure your site’s performance and make sure your images are not contributing unreasonably to the total download time of your page by their big size.
  • Learn the correct syntax of the sizes attribute on the img-tag to ensure the right size of an image is downloaded runtime at the client.

--

--

Ingvild Forseth

I am a software developer who also likes to write. This platform is mostly used to document my process of learning. spinnvild.web.app.