Do Not Use Gatsby Image Above the Fold

Sunset with img tag code overlaid

TLDR: Gatsby Image uses JavaScript to complete the image load process. It should not be used for above the fold images as this adds time to the Largest Contentful Paint. Outcome is base64 is the best in the context of this test.

 

Since the original publishing of this article, Google has acknowledged the issue and are working on a fix. Blur up image loading should not be seen as detrimental to the users experience, due to a better perceived performance. For more info take a look at this tweet: https://twitter.com/addyosmani/status/1277293541878673411. However, if your bonus is based off the Google Page Speed Score – keep reading.

 

Gatsby Image is one of the best packages I have used in the Gatsby/Jamstack ecosystem. Super easy to get to work, and does a lot of the hard work in terms of image loading/speed for you. Connect it to the GraphQL image query and away you go.

 

And then Google released their new Web Vitals

 

This knocked all of my 100% speed scores down off the 100 mark, and I couldn’t understand why. Until I gave the Google Web Vitals documentation a read. This is their 2020 goal:

 

‘The current set for 2020 focuses on three aspects of the user experience—loading, interactivity, and visual stability’.

 

Makes complete sense. Make the user experience as good as possible. No shaky pages, and a smooth journey. But why the low score? I thought Gatsby was the one tool to get 100% SEO scores every time? Turns out it comes down to the Largest Contentful Paint, or LCP.

 

‘Largest Contentful Paint (LCP): measures loading performance. To provide a good user experience, LCP should occur within 2.5 seconds of when the page first starts loading.’

 

Gatsby Image uses JavaScript to manage the image load. This means any image above the fold is not completely loaded until the rest of the site has loaded and the JS has parsed.

I created three different pages as a test to see which way of loading images was the best – Gatsby Image, Standard img/picture tags, or Base64 encoded image. Everything on the each page is exactly the same – apart from how the image is loaded above the fold. I have used webP images where possible, and used Gatsby and GraphQL to process and return the images.

If you want to see what is happening behind the scenes, take a look at the repo: https://github.com/robmarshall/gatsby-image-above-fold-example

 

 

Using Gatsby Image above the fold

This screen grab shows the LCP on a page where an image is loaded using the Gatsby Image package above the fold. Although there is the base64 blurred image in frame from the very beginning – Google is not happy with it. They feel that the image must not be changing if you want the LCP timer to stop.

Google Insights screenshot showing LCP taking 2.6 seconds

Page where data came from: https://thirsty-lichterman-73c92d.netlify.app/

Using Img/Picture Tag above the fold

Here I have rebuilt the img/picture tag using the image data passed out by the Gatsby GraphQL query. Removed any need for JavaScript and let it load naturally.

Google Insights screenshot showing LCP taking 1.8 seconds

Page where data came from: https://thirsty-lichterman-73c92d.netlify.app/alternate/

Using Base64 above the fold

Here I have requested that Gatsby creates a base64 version of the same image shown above. Only the base64 encoded image is used.

Google Insights screenshot showing LCP taking 2.6 seconds

Page where data came from: https://thirsty-lichterman-73c92d.netlify.app/base64/

Outcome

It seems that using Base64 images above the fold is the best way to go. This seems to go again every article ever written about base64 images. The rule is usually: if the image file itself is larger than than the base64 string required to make it – host the image on a server. This is due to the base64 string increasing the size of the HTML file making the initial page heavier. Not only this, as the image is attached directly to the HTML it is not cached. This means if the image is used elsewhere on the site it needs to be re-downloaded.

With that in mind, this approach should only be used for the first page of a sales funnel – where you know that speed/SEO matters.

If you would prefer to be able to cache the image – you would still be better off not using Gatsby Image.

 

I did not use it in this experiment, but Gatsby Image does have a setting to remove the lazy load as well as changing the way the image is loaded. This does not seem to remove the need for JS to complete the loading of the image. To read more about this take a look at the docs: https://www.gatsbyjs.org/packages/gatsby-image/.

 

It would be great to hear your thoughts on the above. Let me know on Twitter: https://twitter.com/robertmars