This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan
<p>I was reading Jake's analysis of <a href="https://jakearchibald.com/2021/f1-perf-part-8/">F1 web sites</a> and it was amazing (but surprising to me) that same issues keep on repeating.</p>
<ul>
<li>Images are not optimized.</li>
<li>JS is blocking, and not optimized (or used in many cases).</li>
<li>Fonts are blocking.</li>
</ul>
<p>Coincidentally around the same time, Ben Galbraith mentioned too me that he was looking for the canonical guidance on how to put an image on the page. Admittedly, I scoffed "It's just an img element innit?", but I bit and had a look.</p>
<p>I don't think I am out of touch with web development, but I certainly missed a trick to feel the pain the ecosystem has with images. On one hand Google is telling you to meet your Core Web Vitals and you must fix your images, but on the other hand the tooling is an absolute massive pain.</p>
<p><a href="https://squoosh.app">Squoosh</a> helps you compress and validate that an image will look good; our guides on <a href="https://web.dev/tags/images/">web.dev</a> give you some concrete advice, but where do you start?</p>
<p>The modern image has gone from a simple <code><img></code> element, to requiring the author to think about the size of the image (in bytes); the size of the image (in resolution) for the target density; The codec being used (remembering the days of JPEG unless you want transparency) because support isn't even across the web; should the image be lazy loaded and pre-fetched?</p>
<p>It's complex. Very complex. You have to be an expert to get an image correct, and it's not actually clear the value an optimized image has. Which is why I think people keep it simple and don't bother.</p>
<p>The complexity of adding images to web pages is why the recommendation to "just use a CDN" is so attractive for the people who can afford it, but it's yet another centralization point and added complexity that you shouldn't have to care about.</p>
<p>I'm not sure what the path is out of this other than consistently making the tooling available to developers to do that right thing, with ease... So, during some recent downtime I built a prototype tool that creates the HTML for a variety of image codecs and image densities that should work well in a large amount of basic image use-cases.</p>
<p><a href="https://just-gimme-an-img.vercel.app/">https://just-gimme-an-img.vercel.app/</a></p>
<picture>
<source
type="image/avif"
sizes="100vw"
srcset="https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-3016.avif 3016w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-1508.avif 1508w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-1006.avif 1006w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-754.avif 754w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-604.avif 604w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-503.avif 503w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-431.avif 431w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-377.avif 377w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-336.avif 336w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-302.avif 302w">
<img
alt="A screen shot of the tool"
src="https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04.png"
srcset="https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-3016.png 3016w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-1508.png 1508w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-1006.png 1006w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-754.png 754w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-604.png 604w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-503.png 503w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-431.png 431w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-377.png 377w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-336.png 336w, https://paul.kinlan.me/images/just-an-image/Screenshot%202021-05-10%20at%2011.34.04-302.png 302w"
sizes="100vw"
loading="lazy"
decoding="async"
height="2104"
width="3016"
style="content-visibility: auto; max-width: 100%; height: auto;"
/>
</picture>
<p>The <a href="https://just-gimme-an-img.vercel.app/">tool</a> is not too complex and not too clever, either. You drop an image on the page and it will:</p>
<ul>
<li>Generate HTML for you to use on your page.</li>
<li>Optimize your source image in the current format</li>
<li>Create an AVIF version of the image.</li>
<li>For the Input and AVIF versions it will create a number of various sized images that the browser will pick based on the resolution.</li>
<li>and it will do it all client-side.</li>
</ul>
<h2 id="why-this-strategy">Why this strategy?</h2>
<p>There is no real intelligence to the tool, I chose a heuristic that was relatively clear and easy to explain. A lot of images that we have trouble optimizing are the hero images on a page, so assuming 100vw makes and AVIF as the alternate preferred source just made sense to me.</p>
<p>AVIF seems amazing (the source image for this blog went from 800KB to 52 KB), yet it's not uniformly supported across the web. Chrome's support is good, so I decided to create this as a preferred <code><source></code> and then falling back to the optimized input image (e.g, PNG or JPG).</p>
<p>Setting the <code>height</code> and <code>width</code> is required for lazy loading and to ensure that we can <code>lazyload</code> and to prevent <a href="https://web.dev/cls/">layout shifts</a>.</p>
<p>Finally, the algorithm will halve the size of the image until it reaches a size of at least 200 pixels. This seemed like a reasonable trade-off in terms of enough sizes that the browser can pick from while also making sure we reduce the chance of artifacts created via sub-pixel resizing.</p>
<h2 id="how-was-it-made">How was it made?</h2>
<p>There's nothing amazingly special, at one point I was going to release it without the client-side image compression, but I wanted to see if it was possible to do everything with web tech.</p>
<p>I'll do a bigger blog post at some point, but the TL;DR is that I managed to work out how to integrate <a href="https://www.npmjs.com/package/@squoosh/cli">squoosh's CLI</a> into an <a href="https://github.com/PaulKinlan/squoosh/tree/kinlan-api/api">API of sorts</a>.</p>
<p>I'm actually very keen to see the Squoosh team work on an web-side embedding API because I think it would be amazing if CMS's such as Blogger or Wordpress just quickly let a person not have to worry about optimizing the image at all.</p>
<h2 id="wrap-up">Wrap up</h2>
<p>Images are harder than they should be to get correct, and I'd love to hear your thoughts and feedback about what we can do to make it easy for developers to be on the happy path for the people that use their service.</p>
This content originally appeared on Modern Web Development with Chrome and was authored by Paul Kinlan