Whenever I run a Page Speed Insights (PSI) test on my post, the hero image, background image, or featured image are painted as the Largest Contentful paint (LCP) element.
What is Largest Contentful paint (LCP)?
The Largest Contentful Paint (LCP) metric reports the render time of the largest image or text block visible within the viewport, relative to when the page first started loading.
Follow Web.dev article on Largest Contentful Paint for more details.
The question usually comes to our mind:
- Should we preload the hero image or featured image?
- Is it worth preloading or not?
Today in this blog post, I’m going to answer your question with real data or Field data using web-vitals JS libraries and provide you reliable 3rd party plugin recommendations.
From the webpagetest result, and the web-vitals JS data, you can decide whether it is the best decision to preload the hero image or not?
From my research, testing, & preloading critical resources like web fonts, and above-the-fold images, and you can see my conclusion.
Setup
- loading=”lazy“
- loading=”eager” and fetchpriority hints
- loading=”eager“, fetchpriority with rel=”preload“
- Preload Test page as an example.
- Fast 3G connection when testing on Webpagetest & Chrome.
- Disable Cache on Chrome, but enable caching so there will be no render blocking issues.
- Disable Image Lazyload & VPI (Viewport Image) in LiteSpeed Metabox so it doesn’t lazyload the featured image and preload because for better control I have manually lazyload for testing.
- I have CSS combine enabled on my page, that is the result, my images are loading earlier in the waterfall chart. If you disable CSS combine or use multiple plugins that load stylesheets, you will see a different result than mine.
Things outside my control:
- Inconsistency in Time for First Byte (TTFB).
- The page is tested in 4G (9 Mbps, 170ms RTT), which means there is less than 100ms latency.
Tools I use when testing
- Chrome Dev Tools
- WebPageTest
Chrome Dev tools
WebPageTest
With a 4G (9 Mbps, 170ms RTT) connection.
The Loading attribute
Here are the supported values for theloading
attribute:
lazy
: Defer loading of the resource until it reaches a calculated distance from the viewport.eager
: Default loading behavior of the browser, which is the same as not including the attribute and means the image is loaded regardless of where it’s located on the page. This is the default, but it can be useful to set explicitly if your tooling automatically addsloading="lazy"
when there’s no explicit value, or if your linter complains if it isn’t explicitly set.
The fetchpriority attribute
Use thefetchpriority
HTML attribute to specify download priority for resource types such as CSS, fonts, scripts, and images when downloaded usinglink
,img
, orscript
tags. It can take the following values:
high
: The resource is a higher priority, and you want the browser to prioritize it higher than usual, as long as the browser’s own heuristics don’t prevent that from happening.low
: The resource is a lower priority, and you want the browser to deprioritize it, again if its heuristics let it.auto
: The default value, which lets the browser choose the appropriate priority.
rel=preload
The preload value of the element’s rel attribute lets you declare fetch requests in the HTML’s, specifying resources that your page will need very soon, which you want to start loading early in the page lifecycle, before browsers’ main rendering machinery kicks in. This ensures they are available earlier and are less likely to block the page’s render, improving performance. Even though the name contains the term load, it doesn’t load and execute the script but only schedules it to be downloaded and cached with a higher priority.
Different loading Attributes scenario when testing:
Loading=”lazy” with Fetchpriority=”low”: The Default behaviour
By default, WordPress will lazyload above-the-fold images using the native lazyloading or Browser Level Lazyloading technique.
Chrome Dev Tools Test
Filmstrip
Waterfall Chart – With CSS Combine
With the loading & fetchpriority attributes set to lazy and low, the loading of the featured image shoots at 19 marks in Chrome Dev Tools waterfall chart when enabling CSS combine Method.
Waterfall Charts – CSS Combine Disabled
With the loading & fetchpriority attributes set to lazy and low when CSS Combine is disabled, the loading of the featured image shoots at 22 marks in Chrome Dev Tools waterfall chart.
Think about if you have multiple plugins loading additional stylesheets, your featured image or viewport image will be loading way lower, this could lead to a Higher LCP value in field and lab data.
WebPageTest
Page Performance Metrics
Filmstrip
Waterfall chart
You can see the waterfall chart, my featured image is loading at 17 marks in WebPageTest results, and when the image is fully loaded LCP is also triggered. See the screenshot below.
Web Vitals – Largest Contentful Paint
Request Details
As you can see from the request details, my featured image is loading at 17 Marks with the priority/fetchpriority of low.
Loading=”eager” with fetchpriority=”high”:
You can see the waterfall chart above, my featured image is loading at the 17 marks wth the priority of low (request details) in WebPageTest results.
Chrome Dev Tools
Filmstrip
The featured image is loading at a 1.5sec mark in Chrome Dev tools Network panels with loading=”eager” & fetchpriority=’high”, which is a huge improvement compared to loading=”lazy” with fetchpriority=”low” attribute, which the featured image is visible in 3.5sec.
Waterfall Chart – Combined CSS enabled
With just changing the loading & fetchpriority attributes, the loading of the featured image shoots from 19 marks to 4 marks in Chrome Dev Tools waterfall chart.
Waterfall Chart – Disable CSS Combine
With just changing the loading & fetchpriority attributes, the loading of the featured image shoots from 19 marks to 7 marks in Chrome Dev Tools waterfall chart.
WebPageTest Result
Page Performance Metrics
Filmstrip
Waterfall chart
The featured image is loading at 5 marks in WebPageTest results, which is much better compare to loading=”lazy” and fetchpriority=”low” attributes.
Loading=”eager”, fetchpriority=”high” & rel=”preload”:
After implementing the loading=”eager” attribute with rel=”preload” hints, the hero image/featured image is loading much quicker and is visible to the users.
Chrome Dev Tools
Filmstrip-
Waterfall chart
After setting the loading=”eager” attribute and rel=”preload” on my featured image, it is loading at 3 marks in the Chrome Dev Tools waterfall chart, but it is not a huge change compared to loading=”eager” and fetchpriority=”high” attribute.
WebPageTest
Page Performance Metrics
Waterfall Chart
Comparison between loading & fetchpriority attributes
Comparison with all the loading attributes screenshot:
- First Screenshot: with loading=”lazy” attribute.
- Second screenshot: with Loading=”eager” attribute
- Third screenshot: With loading=”eager” + rel=”preload”
As you can see from the above comparison, there are benefits of preloading the hero image.
Here is the comparison in webpagetest, if you want to see it for yourselves. But the question is still there.
We can see from the screenshot above, rel=”preload” gives an edge compared to loading=”lazy” and loading=”eager” attribute.
Should I preload hero images? (Dilemma)
Thank you to Phil Walton and Barry Pollard for their incredible tutorials on the web.dev in debugging web vitals in the field and the Smashing Magazine, respectively. Their tutorials help me debug the problems and give me insights on what to do. To answer the question, yes, it depends on your visitor’s screen size and the layout of the website.
Ways to get the Screen resolution
Google Analytics 4 (GA4)
To get your visitors’ screen resolution, head over to the ‘User’ tab, then click the ‘Tech’ and click the Overview to view what browsers, OS, and Device category your visitors are using, etc.
Follow the steps
- GA4 > Reports
- User > Technology
- Technology > Overview
- Scroll down and you will find Active users by Screen resolution
What else can we do with these data?
- You can simulate Screen resolution or screen size on your Dev tools or use LT Browser and see if your hero image is in the viewport or not.
- You can also simulate and test your site in Browserstack or Lambda (Affiliate Link), etc, and do the same thing.
- Using Web-Vitals JS libraries or any RUM tools, send the debug_target in Google Analytics Events data. And figure out whether it is a good idea to preload a hero image or not.
- In Advanced testing, you can use the webpagetest – Desktop Browser Dimensions feature (see the screenshot below).
One way I used to identify or debug the Largest Contentful Paint(LCP) was by implementing Web Vitals JS libraries or other RUM services and analyzing the data with Looker Studio.
Create a horizontal scroll in Elementor with GSAP animation libraries, and use it as an example.
Debug Largest Contentful Paint Elements with Web Vitals JS:
I am currently testing SpeedVitals Real User Monitoring (RUM) (currently in alpha) to visualize and identify the issues.
If you inspect elements on my post and search it with the ‘selector’ below, it will refer to my hero image and title tag.
h1.elementor-heading-title.elementor-size-default
1st CSS selectors refer to my (H1) Heading tag because H1 to H6 are block-level elements and it is visible in the initial viewport of the post.
div.e-hosted-video.elementor-wrapper.elementor-open-inline
The second selector refers to my Feature image because it is the largest element on the page.
Plugins Recommendation:
From my understanding, not all people are tech-savvy like me who love digging around, and sometimes it is not possible to what I did on my landing page or blog post, so it means your best way is to implement it with the help of 3rd parties plugins that will automatically preload critical resources (like CSS, fonts, etc):
- Swift Performance Pro (Affiliate Link): See Version 2.3 (beta) ([NEW] Preload Images) to learn more (if you have a screenshot referring to preloading, please send it to me)
- Automatically Preload “Featured image“ with PHP: Only works with featured image (Attachment below), not with any images visible in the initial viewport or above the fold.
function preload_featured_image() {
if ( has_post_thumbnail() ) {
$id = get_post_thumbnail_id();
$img_html = wp_get_attachment_image( $id, 'large', false, ['loading' => 'eager'] );
// Use regex to extract src, srcset and sizes
if ( preg_match('/src="([^"]+)"/', $img_html, $src_match) &&
preg_match('/srcset="([^"]+)"/', $img_html, $srcset_match) &&
preg_match('/sizes="([^"]+)"/', $img_html, $sizes_match) ) {
echo '<link rel="preload" fetchpriority="high" as="image" href="'.$src_match[1].'" imagesrcset="'.$srcset_match[1].'" imagesizes="'.$sizes_match[1].'" />';
}
}
}
add_action('wp_head', 'preload_featured_image', 0);

- Autoptimize: It doesn’t preload all the featured image, right now you have to manually preload the image.
Conclusion:
I have 180 users that use 1920×1080 screen resolutions according to Google Analytics.
Please keep in mind that Google Analytics (GA) Data might be inaccurate for these reasons:
- Bots can inflate my data.
- Adblockers like uBlock Origin block all any tracking so it means data will not be sent by the browsers to GA Servers.
- Some people preferred disabling JS entirely.
So I decided to test my article, remove unused CSS in the webpagetest with many different screen resolutions, and to my surprise, my feature image (screenshot or links below) triggers my Largest Contentful Paint elements.
Recommendation
The best way to figure out the largest Contentful Paint (LCP) elements is by monitoring and gathering real user data with the help of web-vitals JS libraries or any RUM solution and deciding properly. Because Preloading and Pre-connect can become a double-edged sword if you don’t do it properly. If you love this kind of post, and give you insights on whether to preload or not preload feature images.
You can support me by buying a cup of coffee using any of my Affiliate links presented in the post or hiring me. (This commission comes at no additional cost to you but it will keep the website a little help and write more comprehensive articles just for you)
- Thank you Gijo Varghese for reviewing my post and providing me the FlyingPress image.
- Thank you Nicola Caldognetto for sharing the PHP code on the WP Speedmatters’s Facebook Group.
Thank you for reading till the end. Stay safe and don’t forget to post comments if you find this helpful 🙂