Fix slow hero images & Core Web Vitals
Improve the Largest Contentful Paint by speeding up slow hero images
How To Fix Slow hero images - in short
Hero images are large images on top of a web-page. Those hero images will cause a long Largest Contentful Paint when the hero images are not optimized. 9 out of 10 sites that I am asked to optimize will have issues with the hero images. In this article I will show you different techniques on how to speed up hero images.
Table of Contents!
- How To Fix Slow hero images - in short
- What is a hero image?
- A quick reminder: Hero images, the Core Web Vitals and the Largest Contentful Paint
- Optimizing the hero image and the Largest Contentful Paint
- 1 Preload the hero image or Send 103 headers
- 2 Compress the hero image & use next-gen formats
- 3. Do not use background images, use normal responsive images
- 4. Serve hero images from the main domain & consider a Content Delivery Network (CDN)
- 5. Avoid lazy loading the largest contentful paint images & explicitly eager-load the hero image
- 6. Avoid lay-out shifts caused by the hero image
- 7. Use 2-stage loading to improve the hero Core Web Vitals
What is a hero image?
A Hero Image or sometimes called a called a 'hero header' is a large image with text, often placed at the top of a webpage. A hero image serves as a user's first glimpse of your company and offering because of its prominent placement towards the top of a webpage that usually extends full-width.
A quick reminder: Hero images, the Core Web Vitals and the Largest Contentful Paint
Because of the size of the hero image (it usually spans the entire width of the page a good portion of the height of the visible viewport) this element will become the Largest Contentful Pain element in almost all of the cases.
The largest Contentful Paint is an important Core Web Vitals metric. The largest contentful paint element is the Largest Element that will be painted in the visible viewport of the browser.
Because un-optimized images tend to take up much bandwidth and therefore take a long time to load hero images will often cause bad Largest Contentful Paint Metrics
Optimizing the hero image and the Largest Contentful Paint
There are many techniques for optimizing the hero images and the Largest Contentful Paint. I will explain them here. Most techniques can be combined for even better results!
1 Preload the hero image or Send 103 headers
When you want an element to be available as soon as possible in the browser you could preload that element. Preloading involves using resource hints. Resource hint tell the browser something about the priority of an element and will trigger a very early download of that resource.
<link rel="preload" as="image" href="wolf.jpg" imagesrcset="hero_400px.jpg 400w, hero.jpg 800w, hero_1600px.jpg 1600w" imagesizes="50vw">
In the near future 103 early hints will be supported by chrome browsers. This will make it possible to send resource hints BEFORE the final HTML response has been sent. 103 early hints are expected to be a game changer when it comes to improving the Largest Contentful Paint. If you are interested in learning about early resource hints check out my article.
2 Compress the hero image & use next-gen formats
Compressing images will make their file-size smaller. Smaller file-sizes will take up less bandwidth and are available to the browser as soon as possible. Compressing images can be done in your photo editor, in your CSM (tip: your developer can set the wordpress compression level) or with an online image compression tool
Most slow hero images are slower then they need to be because they are served in the 'wrong' image container like PNG of JPEG. There are much faster alternatives to JPEG and PNG like WebP and AVIF.
For many CMS systems there are conversion plugins that will convert your images to gext-gen format. When image conversion is difficult to integrate into your website a CDN with image conversion support might be the solution you are looking for.
3. Do not use background images, use normal responsive images
Your hero image should be a normal image and never a background image. The usual way of doing hero images is by adding a background image to the hero container and setting the background-size of that container to cover. This will ensure the hero image will fit the screen in all cases.
Background images are bad for Core Web Vitals. Remember that! There is no good reason to ever use background images.
- Background images are loaded at a lower priority
- Background images are not responsive (not unless you really want to complicate things)
- Background images might cause Core Web Vitals issues with most lazy loading libraries.
The way I do it is by adding a normal image in an absolute position and setting the object-fit property of that image to cover. Once I have changed the background image to a normal image I can start using responsive images
Responsive images means that for different devices (mobile,desktop,tablet) a different version of the same hero image can be sent. For a desktop device I might send a huge 1920x1280 hero image while for a mobile device I would only need to send a smaller 400*266 pixels hero image. That is 25 times less data!
- The hero images are now loaded with a higher priority
- I can now use responsive images for the hero image
style.css
<style> #herocontainer{ position:relative; padding:4rem 0 } #heroimg{ object-fit: cover; width: 100%; height: 100%; position: absolute; top: 0; } </style>
index.html
<div id="herocontainer"> <h1>Welcome to my site</h1> <picture> <source type="image/webp" media="(max-width:540px)" srcset="herosm.webp"> </source> <img loading="eager" decoding="async" src="hero.webp" id="heroimg"> </picture> </div>
4. Serve hero images from the main domain & consider a Content Delivery Network (CDN)
All too often I see the largest contentful paint image being served from a different domain, for example 'static.mydomain.com'. These subdomains often point to a CDN. While I encourage the use of a CDN (see below) a setup like this is not advisable. The image on the subdomain requires a new connection to a new server. New connections are costly and will take up valuable time. When the image is served from the main domain (www.mydomain.com for example) the images can be fetched much faster though the already established server connection.
When setup on the main domain a CDN might offer a huge speed increase. Especially when your sites is visited from all over the world. A CDN has servers strategically placed all over the world where your static resources (like images are cached) for fast local response times. This means data does not have to travel all over the world but can be served from a local edge server.
5. Avoid lazy loading the largest contentful paint images & explicitly eager-load the hero image
Make sure that there is no lazy loading being applied to your hero image. Hero images should always load eager.
Many sites, especially WordPress sites, are using some sort of WordPress pagespeed plugin like WP Rocket or WP Core Web Vitals. These plugins usually do a great job in speeding up slow sites but they cannot fix stupid :-)
These plugins will lazy load images that seem like a good candidate to lazy load. If the hero images is not an eager image those plugin will probably also lazy load the hero image.
This, at best, will cause a small delay in the LCP metrics. At worst, especially when JavaScript based lazy loading is activated it will cause a larger delay.
Making images load eager is pretty simple. Just ass loading="eager" to the image and you are done.
<img src="hero.webp" loading="eager" width="800" height="400">
6. Avoid lay-out shifts caused by the hero image
Another common issue I see with hero banners and hero images is that they cause a huge layout shift. These layout shifts may occur for different reasons.
- The hero element is created with JavaScript. Some hero plugins and page builder like elementor are know to rely on JavaScript to render the hero content. Though there is nothing wrong with JavaScript make sure the hero element renders the same without JavaScript.
- The fonts in the hero element cause a layout shift. The hero element usually contains some large text with a call to action and a tagline. Make sure these large fonts do not cause a layout shift.
- Missing image dimensions. When the hero image is not a cover images (either as a background image or a an absolute positioned image) missing image dimensions (width and height) will certainly cause a large layout shift.
While fixing the layout shift not improve the Largest Contentful Paint, it will improve the Core Web Vitals of the page. For more information on how to fix the layout shift please read this in-depth guide on how to fix the layout shift!
7. Use 2-stage loading to improve the hero Core Web Vitals
2-stage loading is an fast technique that we apply to all our images. We first serve an extremely low quality image that is expected to download much earlier then the larger high quality image. Once the low quality image has been painted on the screen we the browser is triggered to fetch the high quality image in the background. Once the high quality images has been downloaded the low quality images will be replaced by the high quality image.
There are 3 methods of 2-stage loading. The first two are methods you should consider. The last one is one you should not do.
Stage 1: low quality webp 3-5kb
Stage 2: high quality webp 20-40kb
1. Full 2-stage loading
With full 2-stage loading the first loq quality image has the exact same dimensions (width and height) as the original hight quality image.
The result of this 2-stage loading is that the largest contentful paint element will be the much faster, low quality image (which will then lazily be swapped). The swapping of the image will all happen so fast that a casual visitor will probably never notice. The result of this technique is that the LCP is painted much earlier the page appears 'ready' much sooner which contributes to a far better user experience and improved Core Web Vitals.
2. Smaller in-line placeholders
The smaller placeholder is a pretty cool technique that has one drawback: it does not improve the Core Web Vitals. It is still a great technique because it improves the user experience.
The basic idea is the same as for the 2-stage loading technique but in stead of one low quality image with the same dimensions a much smaller images with smaller dimensions is placed inline though a data uri. The final hero image which will be the largest contentful paint image is still downloaded in the background. This trick will not improve the Largest Contentful Paint but will make the page appear ready even faster then the 2-stage loading technique
3. Transparent placeholders
A common 2-stage loading technique and a method to trick the browser into sending an early Largest Contentful Paint metric is to use transparent svg elements. Those elements are small and can be placed inline, just like the smaller inline placeholder.
Using an inline svg elements and swapping them is actually a lazy loading technique. The advantage of this technique is that it works cross-browser.
Lazy loading, of course should only be applied to elements outside of the viewport. In this case the transparent svg element will only delay the real hero image and has no added value for your visitor. Where the paint metrics might be great, the UX of the page will actually worsen.
That is why the hero image should always be loaded eagerly without tricks that cause a bad UX.
Stop Guessing, Start Measuring
I use Core/Dash to optimize my clients sites. So Should You.
- Easy set up.
- Over 5000 happy clients
- Free trial, No strings attached