Beginners Guide to Web Performance: Optimizing Images
Tags: sitespeed, webdev, webperf, images
Published: 2021-09-06 21:29:50

## How to Improve Web Performance and Site Speed by Optimizing Images
### Table of Contents
* [Introduction](#intro)
    - [Previous Site Speed Strategies](#previous-strategies)
* [How to Optimize Images](#optomize-images)
    - [Resize & Compress Images](#resize-images)
    - [Lazy-Load Images](#lazy-images)
    - [Set Width & Height Attributes](#attribute-images)
    - [Use the Picture Element](#picture-element)
* [Conclusion] (#conclusion)

### Introduction <a name="intro"></a>
The past year I've really made an effort to dig into site speed and optimizing sites based on audits from Google Page Speed Insights because of the now-released Core Web Vitals. Even if this didn't affect ranking, it's good practice to minimize as much data being loaded as possible and to provide the user with as smooth an experience as you can.

I started off by taking the [Web Performance course by Scott Jehl](https://scottjehl.com/lfwp/), which is a great starting point if you are coming into this completely new. The course explains all the stages, what all the metrics mean, how to measure your site, and then goes into detail on how to improve each of the aspects. I highly recommend this course if you want a thorough primer on the subject.

#### Previous Site Speed Strategies <a name="previous-strategies"></a>
Before researching newer methods, the predominant strategy was to minimize the entire page size, which is almost no longer relevant as a metric. Total page size doesn't tell you what the user is experiencing as they browse, and putting a necessary gallery on a page shouldn't doom your rankings. Granted, a very large page size may indicate images need compression, but not always. Now the strategy is concerned with loading items only when the user needs them, versus years before where the consensus was to reduce the total number of items loaded on the page overall.

### How to Optimize Images <a name="optomize-images"></a>
I've outlined the steps I've taken to optimize images on sites based on recommendations from web experts and from personal experience. These are relatively easy to implement and are a good starting point for site optimization.

#### Resize and Compress Images <a name="resize-images"></a>
This has been relevant for years now, but don't load a giant 1000x800 image for a 100x100 thumbnail. Sometimes I load a site and it's very obvious that a small thumbnail image above the fold is loading the full-sized image because it takes 2-3 seconds to download. That large image is loading extra bytes that serve no advantage to users because they will not be able to see the full details.

Getting the sizing perfect can be difficult if you're using a CMS and the same image is used in different situations, but you want to use the smallest image needed when possible. I use two free tools in combination for bulk image editing:
* [Bulk Resize Photos](https://bulkresizephotos.com/): Allows dragging and dropping of multiple images, setting max widths, converting pngs to jpgs, and a whole bunch of other actions that I used to have to do in Photoshop. I don't use the compression option here, only resizing.
* [Image Optim](https://imageoptim.com/mac): Mac only, can set custom compression settings and remove heavy metadata. I use this after resizing the images in Bulk Resize since the compression settings here are much more comprehensive.

#### Lazy-Load Images <a name="lazy-images"></a>
I had been waiting for this attribute for years, and now you can safely use it in all the major browsers. If the attribute is not compatible in the browser, then it just doesn't do anything:
```<img src="sample.jpg" loading="lazy" alt="Sample" />```
This tells the browser not to load the image until it is in the user's viewport, meaning if you have a gallery that is well below the fold, you won't have to worry about those images clogging up the LCP (largest contentful paint). Keep one thing in mind however:

>**Do not use the loading="lazy" attribute for images that are definitely ABOVE the fold**

If the image needs to be visible immediately to the user, do not use this attribute, as this may negatively impact LCP or CLS (cumulative layout shift).

##### Compatible Plugins
If you want to guarantee lazy-load across all (JavaScript-capable) browsers and not just images, I've used [Vanilla Lazyload](https://github.com/verlok/vanilla-lazyload) a couple years ago with success, but as this relies on using a `data-src` attribute, you will get W3C validation errors unless you also set a `src` attribute. But you don't want to set the `src` to a real image, because this will nullify the whole point of using the plugin, so set it to a 1x1 pixel "image" that will immediately get replaced by the `data-src` once the image scrolls into view.

src=`"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"`

#### Set Image Width and Height Attributes <a name="attribute-images"></a>
Both these attributes surprisingly have a long, complex history. When I built web sites as a kid, CSS was not standard yet, and you would have to set a width and height on image attributes. Then when I returned to web development as an adult, these attributes were discarded because they interfered especially with art direction, where the aspect ratio of an image changed going from desktop to mobile.

```html
<img src="logo.jpg" alt="" loading="lazy" width="200" height="300">
```

And here we are now, with the recommendation to set both these attributes back again to reduce CLS (cumulative layout shift) because the browser considers these values a ratio, rather than exact pixels. If the page is loading and the width and height are not set, then the browser has no idea what dimensions your image is, and the layout will shift considerably once the image finishes loading, which is disruptive to the user.

If you have images that change aspect ratios depending on the screen size, then you will have to use either the image `srcset` attribute or the `<picture>` element in order to serve different images based on the screen size. I would also make sure that the CSS rules don't accidentally stretch or warp the images depending on how you have your rules set up.

#### Use the Picture Element to Serve WEBP or Other Newer Formats <a name="picture-element"></a>
Even with resizing and compressing images, if you are using either JPGs or PNGs, these files will still be larger than WEBP images, one of the newer, widely-accepted image formats. I've noticed about a 30% decrease in image size once converting to WEBP, but I still make sure to serve the original image format for maximum browser compatibility.

I use [Squoosh](https://squoosh.app/) to convert individual images to WEBP. I haven't found a good free bulk tool yet, and I still find I have to mess with the settings to make sure the image still looks good after being compressed. 

```html
<picture>
   <source srcset="image.webp" type="image/webp">
   <source srcset="image.jpg" type="image/jpeg">
   <img src="image.jpg" alt="Image 1" loading="lazy">
</picture>
```

Here the browser will load WEBP images for browsers that are compatible, and if not, then it will serve the JPG image.

##### What about Background Images?
If you are loading a WEBP background image via CSS, there's no easy way to fallback to JPG since the `<picture>` element only works for HTML images. I've read about setting server or rewrite rules to serve WEBP for people who can view them, and then automatically loads the older version for people who can't, but I haven't tried this method yet. You would have to have 2 versions of every image on the server, and this would replace the `<picture>` element method since the server would handle switching out the images.

A question I've started asking myself is how important is serving the background image on older browsers. If the image is purely decorative, then does this even need to show up on the older browser at all? Can the images be loaded only on newer browsers as part of progressive enhancement? This is something that I'm still figuring out. I've had to support older browsers for so long in my work - not just support but make sure they look exactly the same as newer browsers - but if we're slowing down all browsers just so the minority of older ones see the exact same design, is this really helpful for everyone? Lately I've been leaning towards "no".

### Conclusion <a name="conclusion"></a>
I hope you are able to get started with web performance and site optimization with images. This can get tricky once images are served dynamically and art direction is considered, but these are simple steps to get started to help make web sites load more efficiently for everyone.