Watching your (image) weight

There are a few basic rules that you can follow to ensure that the images you add to your site are suitable for consumption across all devices and connection speeds.

Update: Andy emailed to say that he worked through this article and has now taken the page from 35Mb to 8Mb. Awesome to see!

Today I came across a tweet that was promoting and linking to a wonderful talk done by Andy Clarke from Stuff and Nonsense.

I followed the link, mainly because I love the stuff that Andy writes and speaks about, and began reading the article.

Designing inspired style guides presentation slides and transcript

After the introductory paragraph I came across the next bit

NB: This page contains 35Mb of images. I’ve optimised them as much as possible, but you probably don’t want to load this page using your mobile data plan

First things first — Kudos to Andy for warning his readers that the page was going to be pretty big. It shows that Andy is well aware of the issue, who it could effect, and provided instructions as soon as he could.

The downside is that by the time I’m reading this it’s too late to avoid it all together, the images are already busy downloading.

One saving grace is that due to the number of images and the size of the download you can catch it at this point and save your bandwidth… not ideal but better than nothing. But what if I did want to see more of those images that go along with the transcript? Maybe not all of them, but as many as I look at.

I took some time out and checked if there was anything else to be done.

*Note* — It’s worth saying twice, this is in no way a dig at Andy and the effort he put in to sharing content with the wider web, this is about offering other possible solutions to the problem so that everyone might also learn something more performance focussed.

Now that is cleared up, let’s take a look.

Seeing the issue

The first thing I wanted to do was see how things were loading. Using Chrome and the Dev Tools that ship with Chrome I

  • Opened up the Network Panel
  • Set the Throttling to Good 3G
  • Set it to no cache
  • Refreshed the page
Chrome browser Dev tools Network tab

Once the page had finished loading there were a few things that I noticed:

  1. All of the images were being served as PNG files (likely a default export option for Keynote)
  2. All of the images were being loaded regardless of whether I was going to see them
  3. Every image required its own HTTP request (many requests, lots of latency)

Armed with that information I knew there were a few things that could be done to improve this valuable resource.

Getting the files locally

The next step was to get all of the images onto my local computer so I could start working on them. This can be achieved by visiting the page you want to work on and going File » Save Page As » Webpage, Complete. 

I saved this down to my Desktop — where I apparently save everything that has ever existed in the history of everything — and I was ready to get to work.

PNG vs JPG — where and when to use

The first thing I noticed was that all of the slide images were PNG. There are a few rules of thumb when it comes to choosing the image format that you want to use and often PNG can cause a lot of additional file size bloat if you don’t follow some rules.

You should choose PNG when

  1. The image is block colours, think Vector style images (logos, icons* etc)
  2. You need a transparent background** (using PNG24)

You should choose JPG when

  1. The image is more rasterized, like a photo

* technically you should probably look to SVG’s for logos & icons if you can, that way it’s a Vector file and it will scale and remain crisp at any resolution or size
** you can get transparent backgrounds using WebP images too

Looking through the slide images I found that most of the images were better suited to JPG. While you should hand pick the images for PNG and JPG to make sure you get the best overall fit I was working quickly and chose to change them all to JPG.

*** As a side note you can specify the file type of the image when exporting from Keynote if you require

Image type options when exporting from Keynote

Batch updating PNG to JPG

I’ve got a saved Automation Sequence on my mac that allows me to right click and change a file from PNG to JPG. It’s really helpful for me because all the screenshots I take on the mac are in PNG format and 90% of the time I need them in JPG. Unfortunately, the automation only works on one file at a time and with around 150 images to process I needed something else.

Photoshop has an Image Processor option, Files » Scripts » Image Processor which allows me to do the following

  1. Select the folder of images I want changed
  2. Select the location for the files that will be updated
  3. Choose to save out as JPG
  4. Choose the quality of the image to be saved (I went with 4, but you can choose anywhere between 1-12)
Photoshop Image Processor Options for batch updating PNG -> JPG

After a minute or so all of the images had been processed and saved out into their own JPEG folder.

This alone took the size from 35Mb down to 10.4Mb.

Losslessly Compressing JPGs with ImageOptim

Although there was a large saving of image sizes from the last step you can always shave a few more kilobytes off an image by running it through ImageOptim (free). The great thing with ImageOptim reduces the file size but does not affect the visual quality of the image. Win win!

I have ImageOptim permanently in the dock so it was just a matter of dragging the JPEG folder onto the icon in the doc and let them process. Another minute later and it had managed to take it down from 10.4Mb to 6.1Mb.

Updating the images in the post

Now we have all of our fully optimised images it’s time to update the post, and while I don’t know what Andy uses to manage the site I can at least cover off what I think would be the easiest approach.

There are only two things that have changed since the start of this proces:

  1. The images are much smaller
  2. The file names have changed from image01.png to image01.jpg

With that knowledge, our next steps would include

  1. Upload all of the images onto the web server and into the same folder that you had the original PNG files (because they are different file names you won’t overwrite anything)
  2. Get the source HTML of the article and do a Find & Replace: find .png and replace with .jpg

The last step is to republish the updated HTML and Voila, you’ve saved every visitor almost 30Mb!!! Considering how popular Andy and his articles are around the web community we could give an estimate that 10,000 people will see the article which equates to a shade under 300 Gigabytes of data (and bandwidth that doesn’t have to be paid for).

Bonus Extra’s to save page weight & improve performance

I think you’ve all done a wonderful effort thus far, but there’s always something else that we could be doing. From the initial potential issues I mentioned at the beginning of this article, we have only really fixed the first one and we’re still left with the other two:

  1. All of the images were being loaded regardless of whether I was going to see them
  2. Every image required its own HTTP request (many requests, lots of latency)

So how do we go about fixing these?

Lazy Loading Images with Lazy Sizes

LazySizes is a javascript plugin that allows you to only load in images that are within the current viewport, or you can set a threshold that will start loading the image as it approaches the viewport.

In simple terms: As you scroll down the page the browser will start downloading the images just before the image would normally come into view.

The great thing about this approach is that on a page such as this one where there are 150 images the reader might only get to the first 20 slides before leaving. Without lazy loading they would be penalised by downloading all 150 images and never see 130 of them, but with lazy loading they only “pay for what they eat”… so to speak.

To implement Lazy Sizes you need to add the JS….

<script src="lazysizes.min.js" async=""></script>

… and then for all your images you want to lazy load you update the img tag to include the .lazyload class and update the src to data-src

<img data-src="image.jpg" class="lazyload" />

There are some great examples on the Lazy Sizes project site.

Improving latency with H2

The final point that could be fixed is to improve on the latency for these request.

The way that the web works on HTTP1.1 is that for every asset that is needed — an image, font, CSS, JS etc — you need to make a HTTP request back to the server. Each request takes a little bit of time and burns a little bit of battery. There is also the issue that there are only so many concurrent requests that can occur at any one time, so when you’re requesting lots of files it can be a little time-consuming.

There is a new kid in town now, HTTP2, and it’s coming for HTTP1.1.  The improved protocol does quite a few cool things but for the purpose of this article it will allow a single request and connection to be made, and ALL of the files will be returned all at once. In other words where previously a request for 150 files would require 150 HTTP requests, with HTTP2 it only takes a single request.

There are a few requirements for H2 to work though:

  1. Your server needs to support and be configured to use H2
  2. The users browser requesting the page needs to support (support is good though)
  3. The site needs to be running on HTTPS

To get past issue 1 & 3 (after all you can’t do much about the users browser) you can turn to something like Cloudflare who offer both free HTTPS and, once you’re on HTTPS, automatically serves all your content over HTTP2.

Extra Bonus, Responsive Images

An added+added bonus for this would be the addition of a responsive images solution.

There are a number of people that will be accessing Andy’s article on a super high-quality retina giant screen, and more that will access it on a smaller device with a crappier screen. The crux of this is that you don’t need to serve the same sized image to everyone, because everyone will have different sized screens that will be better off with different sized images.

If you want to go into detail on responsive images then this article from Eric Portis is a great place to start. Essentially SRCSET allows you to provide the browser with information about both the images that are on your server (the srcset part) and the way in which your design responds in the viewport (the sizes part).

<img 
      src="horse-350.jpg" 
      srcset="horse-350.jpg 350w,
      horse-500.jpg 500w,
      horse-1024.jpg 1024w,
      horse.jpg 2000w" 
      sizes="(min-width: 64em) 70vw,
      (min-width: 37.5em) 95vw,
      100vw"
      alt="A horse" />

This allows the browser to choose the most appropriately sized image for the job (and thus smaller images when small images are needed, and larger images when larger ones are needed).

Conclusion

Images have become a real issue on the web. Year after year the size of web pages are growing larger and the largest cause for this is the increase in the size of images. As you can see from this article, if you are able to spend a little bit of time looking at the types of images you’re serving, how you’re serving them, then you can save everyone a lot of time and bandwidth.

Subscribe to our Newsletter

Add your email address and receive an email every Friday covering off everything worth knowing about building your websites responsively.