HTML code snippet showing a link rel=preload tag with fetchpriority=high for a hero imageDetailed guide

Image Preloading Guide: Practical Implementation to Reduce LCP

View contents

Image Preloading Guide: Practical Implementation to Reduce LCP

Introduction

This guide covers how to identify your LCP image, correctly implement rel="preload" and fetchpriority="high", preload responsive images with srcset, and avoid the mistakes that cancel out these techniques' benefit. The UXR SEO Analyzer reports whether the detected LCP image lacks priority signals.

If you need the conceptual background first, see Image Preloading Explained.

Step 1: Identify the LCP Image

Use Chrome DevTools' Performance panel or a Lighthouse report to identify which element is flagged as Largest Contentful Paint. On most content pages it's the hero image or the article's featured image.

Step 2: Basic Preload for an HTML Image

<head>
  <link rel="preload" as="image" href="/hero.jpg" fetchpriority="high">
</head>
<body>
  <img src="/hero.jpg" fetchpriority="high" width="1200" height="600" alt="Image description">
</body>

Note that we declare fetchpriority="high" both on the <link rel="preload"> and on the <img> tag to maximize the priority signal at both points of the loading pipeline.

Step 3: Preloading Responsive Images

When the LCP image uses srcset/sizes, the preload must replicate those same attributes using imagesrcset and imagesizes so the browser preloads the correct variant:

<link
  rel="preload"
  as="image"
  href="/hero-800.jpg"
  imagesrcset="/hero-400.jpg 400w, /hero-800.jpg 800w, /hero-1200.jpg 1200w"
  imagesizes="(max-width: 600px) 100vw, 800px"
  fetchpriority="high">

Without imagesrcset/imagesizes, the browser could preload a different variant than the one the <img> ultimately uses, wasting the bandwidth of that early download.

Step 4: Preloading a CSS Background Image

If the LCP element is a background-image defined in CSS, the browser doesn't discover it until it processes that CSS rule—that's why a preload in the <head> is essential for early discovery:

<link rel="preload" as="image" href="/hero-bg.jpg" fetchpriority="high">
<style>
  .hero { background-image: url('/hero-bg.jpg'); }
</style>

Step 5: Verify the Result

  1. Open DevTools → Network panel and confirm that hero.jpg appears among the first requests, with "High" priority.
  2. Run Lighthouse and compare the LCP timestamp before/after the change.
  3. Confirm there's no loading="lazy" on the same image—that's the mistake that cancels out the preload's effect.

Common Mistakes

MistakeConsequenceFix
Preload href different from the actual srcThe browser downloads a resource that's never used, speeding up nothingSync the preload URL exactly with the <img>'s
Preloading more than one image as "high"Priority gets diluted and competes with the real LCP imageReserve fetchpriority="high" for the LCP element only
Combining preload with loading="lazy"Contradictory signals; the browser may ignore the preloadNever use lazy loading on the LCP image
Preload without the as="image" attributeThe browser doesn't assign the correct priority to the resourceAlways declare as="image"

Framework Implementation

Next.js

The next/image component exposes a priority prop that, when applied to the LCP image, automatically generates both the corresponding <link rel="preload"> in the <head> and the fetchpriority="high" attribute on the rendered element, and also disables lazy loading for that specific image:

import Image from 'next/image';

export default function Hero() {
  return (
    <Image
      src="/hero.jpg"
      width={1200}
      height={600}
      alt="Image description"
      priority
    />
  );
}

Nuxt / Vue

The <NuxtImg> component from @nuxt/image accepts an equivalent preload prop that generates the same pair of signals (preload link + fetchpriority) during server-side rendering.

Static HTML / Astro

On sites without a built-in image framework, the manual implementation shown in the earlier steps is the only option, so it's worth wrapping it in a reusable component or partial rather than repeating the pattern in every template.

Preloading Multiple LCP Candidates

On sites with dynamic content (for example, a feed where the first item changes per user), you may not know at build time exactly which image will be the LCP. A common strategy is to preload the first feed item's image server-side, since it's statistically the most likely LCP candidate, and accept that the benefit will be smaller in atypical cases.

Continuous Monitoring of LCP After Implementation

Once you've implemented the preload, validate the real-world impact (not just in the lab) by integrating the field metric with the web-vitals library:

import { onLCP } from 'web-vitals';

onLCP((metric) => {
  console.log('This user\'s real LCP:', metric.value, 'ms');
  // send the value to your analytics system alongside the page URL
});

Compare the distribution of field LCP before and after the change for at least a week, since variable network conditions across users can mask improvements that are consistent in aggregate.

Font Preloading vs. Image Preloading

It's common for a site to already use rel="preload" for critical web fonts, but not extend it to the LCP image. Both resources compete for the same initial bandwidth budget, so adding an image preload without reviewing how many preloads already exist can dilute the priority of all of them. As a general rule, limit critical preloads (main font + LCP image) to a maximum of 2-3 resources per page; adding more preloads than are actually critical to the initial render reduces the benefit of each one.

Conditional Preload by Viewport

In layouts where the LCP image changes between mobile and desktop (for example, a different hero per breakpoint), you can use the media attribute on <link rel="preload"> so the browser only downloads the relevant variant based on viewport width, avoiding an unnecessary download of both images:

<link rel="preload" as="image" href="/hero-mobile.jpg" media="(max-width: 600px)" fetchpriority="high">
<link rel="preload" as="image" href="/hero-desktop.jpg" media="(min-width: 601px)" fetchpriority="high">

Quick Decision Summary

QuestionAnswer
Is this the page's LCP image?Yes → apply preload + fetchpriority. No → leave it alone.
Is the LCP image in a CSS background?Yes → preload is mandatory for early discovery.
Are there already 2-3 critical preloads on the page?Yes → evaluate whether you really need to add another.
Does the image have loading="lazy"?Yes → remove it if it's the LCP image.

Working Alongside a Content Security Policy

Sites with a strict Content Security Policy sometimes block preload hints unintentionally if the img-src directive doesn't cover the CDN domain the preloaded image lives on. If a preload silently has no effect, check the browser console for CSP violation warnings before assuming the technique itself failed—this is one of the more common reasons a correctly written preload tag doesn't actually speed anything up in production.

When Preloading Can Backfire

Preloading isn't free: every preloaded resource competes with everything else the page needs during the critical loading window, including render-blocking CSS and the main document itself. Preloading a large, unoptimized image (say, several megabytes because it skipped compression or a modern format) can starve other critical requests of bandwidth and make overall page load worse even as it speeds up that one image. Preload should always be paired with the other image performance basics—correct format, compression, and appropriate dimensions—rather than used as a substitute for them.


References

  1. web.dev - Preload critical assets to improve loading speed
  2. web.dev - Optimize resource loading with the Fetch Priority API
  3. web.dev - Preload responsive images
  4. web.dev - Optimize Largest Contentful Paint
  5. Chrome Developers - LCP request discovery
  6. Chrome Developers - Avoid chaining critical requests

Related articles

Related version

Introduction

Image Preloading: How rel=preload and fetchpriority Speed Up Your LCP

Preloading the LCP image with rel=preload or fetchpriority=high is one of the lowest-effort, highest-impact changes to improve Largest Contentful Paint.

Category hub

Hub

Images Seo Hub

Images are critical to user engagement—but they can also be your website's biggest performance bottleneck

In the same category

Detailed guide

Lcp Optimization Guide

Largest Contentful Paint (LCP) measures when the largest content element becomes visible to users

Detailed guide

Fetchpriority Optimization Guide

This comprehensive guide walks you through advanced fetchpriority implementation strategies

Detailed guide

Lazy Loading Best Practices Guide

Lazy loading is one of the most effective techniques for improving page performance—when used correctly

Other topics

Hub

Performance Seo Hub

Performance is a critical ranking factor and directly impacts user experience