Performance 15 min read

Image Preloading and Priority Hints

Master image preloading and fetchpriority for optimal performance. Learn when to preload, priority hints, responsive preloading, and avoiding common mistakes.

By ImageGuide Team · Published January 19, 2026 · Updated January 19, 2026
preloadingfetchprioritylcpperformanceweb performance

Preloading tells the browser to fetch critical images early. Priority hints control the order of resource loading. Together, they’re essential tools for optimizing Largest Contentful Paint (LCP).

Understanding Resource Priority

Browsers prioritize resources differently based on type and context:

Resource TypeDefault Priority
Main HTMLHighest
CSS (blocking)Highest
FontsHigh
Scripts (blocking)High
Images (in viewport)Medium
Images (out of viewport)Low
Async scriptsLow

Images discovered late in the HTML or loaded via CSS start fetching late. Preloading solves this.

Basic Preloading

The <link rel="preload"> element tells the browser to fetch a resource immediately.

Simple Image Preload

<head>
  <link rel="preload" as="image" href="hero.jpg">
</head>
<body>
  <img src="hero.jpg" alt="Hero image">
</body>

Required Attributes

AttributePurposeRequired
rel="preload"Declares preloadYes
as="image"Resource typeYes
hrefResource URLYes
typeMIME typeFor modern formats
imagesrcsetResponsive sourcesFor srcset
imagesizesDisplay sizesWith imagesrcset

Preloading Modern Formats

Specify the type to help browsers that don’t support the format skip it:

<!-- Browser will skip if it doesn't support AVIF -->
<link rel="preload" as="image" href="hero.avif" type="image/avif">

<!-- Fallback preload for wider support -->
<link rel="preload" as="image" href="hero.webp" type="image/webp">

Note: You generally only need to preload one format. The browser uses the first supported format from your <picture> element.

Responsive Image Preloading

For responsive images with srcset, use imagesrcset and imagesizes:

<head>
  <link
    rel="preload"
    as="image"
    href="hero-1200.jpg"
    imagesrcset="
      hero-600.jpg 600w,
      hero-900.jpg 900w,
      hero-1200.jpg 1200w,
      hero-1800.jpg 1800w
    "
    imagesizes="100vw"
  >
</head>

<body>
  <img
    src="hero-1200.jpg"
    srcset="
      hero-600.jpg 600w,
      hero-900.jpg 900w,
      hero-1200.jpg 1200w,
      hero-1800.jpg 1800w
    "
    sizes="100vw"
    alt="Hero"
  >
</body>

The browser selects the appropriate source based on viewport and DPR, just like with regular srcset.

Responsive Preload with Modern Formats

<head>
  <link
    rel="preload"
    as="image"
    href="hero-1200.avif"
    imagesrcset="
      hero-600.avif 600w,
      hero-900.avif 900w,
      hero-1200.avif 1200w
    "
    imagesizes="100vw"
    type="image/avif"
  >
</head>

Priority Hints: fetchpriority

The fetchpriority attribute gives more granular control over resource priority.

Using fetchpriority

<!-- High priority: LCP images -->
<img src="hero.jpg" fetchpriority="high" alt="Hero">

<!-- Low priority: below-fold, decorative -->
<img src="decoration.jpg" fetchpriority="low" loading="lazy" alt="">

<!-- Auto: browser decides (default) -->
<img src="content.jpg" alt="Content">

Values

ValueEffect
highIncrease priority above default
lowDecrease priority below default
autoBrowser decides (default)

Combining with Preload

<head>
  <link
    rel="preload"
    as="image"
    href="hero.jpg"
    fetchpriority="high"
  >
</head>

<body>
  <img src="hero.jpg" fetchpriority="high" alt="Hero">
</body>

When to Use Each Priority

fetchpriority=“high”

  • LCP/hero images
  • Above-the-fold critical images
  • Product images on e-commerce landing pages

fetchpriority=“low”

  • Decorative images
  • Below-fold images (combine with lazy loading)
  • Carousels beyond the first slide
  • Images in collapsed accordions
<!-- Hero: highest priority -->
<img src="hero.jpg" fetchpriority="high" alt="Hero">

<!-- Product grid: first visible row -->
<img src="product-1.jpg" fetchpriority="high" alt="Product 1">
<img src="product-2.jpg" fetchpriority="high" alt="Product 2">

<!-- Below fold: low priority + lazy -->
<img src="product-5.jpg" fetchpriority="low" loading="lazy" alt="Product 5">

Media-Based Preloading

Preload different images for different viewport sizes:

<head>
  <!-- Desktop hero -->
  <link
    rel="preload"
    as="image"
    href="hero-desktop.jpg"
    media="(min-width: 768px)"
  >

  <!-- Mobile hero (different image) -->
  <link
    rel="preload"
    as="image"
    href="hero-mobile.jpg"
    media="(max-width: 767px)"
  >
</head>

This is essential for art direction where different images are served at different breakpoints.

Preloading Background Images

CSS background images are discovered late. Preload them:

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

With Media Queries

<head>
  <link
    rel="preload"
    as="image"
    href="hero-mobile.jpg"
    media="(max-width: 767px)"
  >
  <link
    rel="preload"
    as="image"
    href="hero-desktop.jpg"
    media="(min-width: 768px)"
  >
</head>

Preconnect and DNS-Prefetch

If images come from external domains, reduce connection time:

<head>
  <!-- Full connection (TCP + TLS) -->
  <link rel="preconnect" href="https://cdn.example.com">

  <!-- DNS only (lighter, wider support) -->
  <link rel="dns-prefetch" href="https://cdn.example.com">

  <!-- Then preload the image -->
  <link rel="preload" as="image" href="https://cdn.example.com/hero.jpg">
</head>

Best practice: Use preconnect for critical image CDNs, dns-prefetch for others.

When to Preload

Good Candidates for Preloading

  1. LCP images: Hero images that determine LCP score
  2. Above-fold images: Visible on initial load
  3. CSS background images: Not discovered until CSS parses
  4. Images loaded by JavaScript: Not in initial HTML
  5. Images after redirects: The browser discovers them late

Don’t Preload These

  1. Below-fold images: Use lazy loading instead
  2. All images: Preloading everything defeats the purpose
  3. Low-priority decorative images: Wastes bandwidth
  4. Already high-priority resources: Already prioritized by browser

The Preload Limit

Browsers limit concurrent connections and preload priority. Too many preloads dilute the benefit:

<!-- BAD: Too many preloads -->
<link rel="preload" as="image" href="image-1.jpg">
<link rel="preload" as="image" href="image-2.jpg">
<link rel="preload" as="image" href="image-3.jpg">
<link rel="preload" as="image" href="image-4.jpg">
<link rel="preload" as="image" href="image-5.jpg">
<link rel="preload" as="image" href="image-6.jpg">

<!-- GOOD: Only critical images -->
<link rel="preload" as="image" href="hero.jpg">
<link rel="preload" as="image" href="logo.svg">

Rule of thumb: Preload 1-3 images maximum per page.

LCP Optimization Pattern

The complete pattern for optimal LCP image loading:

<!DOCTYPE html>
<html>
<head>
  <!-- Preconnect to image CDN -->
  <link rel="preconnect" href="https://cdn.example.com">

  <!-- Preload LCP image with responsive sizes -->
  <link
    rel="preload"
    as="image"
    href="https://cdn.example.com/hero-1200.avif"
    imagesrcset="
      https://cdn.example.com/hero-600.avif 600w,
      https://cdn.example.com/hero-900.avif 900w,
      https://cdn.example.com/hero-1200.avif 1200w
    "
    imagesizes="100vw"
    type="image/avif"
    fetchpriority="high"
  >
</head>
<body>
  <picture>
    <source
      srcset="
        https://cdn.example.com/hero-600.avif 600w,
        https://cdn.example.com/hero-900.avif 900w,
        https://cdn.example.com/hero-1200.avif 1200w
      "
      sizes="100vw"
      type="image/avif"
    >
    <img
      src="https://cdn.example.com/hero-1200.jpg"
      srcset="
        https://cdn.example.com/hero-600.jpg 600w,
        https://cdn.example.com/hero-900.jpg 900w,
        https://cdn.example.com/hero-1200.jpg 1200w
      "
      sizes="100vw"
      alt="Hero"
      width="1200"
      height="600"
      fetchpriority="high"
    >
  </picture>
</body>
</html>

Measuring Impact

Chrome DevTools

  1. Network tab: Check when preloaded resources start loading
  2. Performance tab: Look at LCP timing
  3. Lighthouse: Check “Preload Largest Contentful Paint image”

Performance Observer

new PerformanceObserver((entryList) => {
  for (const entry of entryList.getEntries()) {
    console.log('LCP candidate:', entry.element);
    console.log('LCP time:', entry.startTime);
  }
}).observe({ type: 'largest-contentful-paint', buffered: true });

Resource Timing

// Check if preload helped
performance.getEntriesByType('resource').forEach(entry => {
  if (entry.name.includes('hero')) {
    console.log('Hero image timing:', {
      fetchStart: entry.fetchStart,
      responseEnd: entry.responseEnd,
      duration: entry.duration
    });
  }
});

Server-Side Considerations

HTTP/2 Server Push (Deprecated)

HTTP/2 Server Push is deprecated and being removed from browsers. Use preload instead.

103 Early Hints

Servers can send preload hints before the full response:

HTTP/1.1 103 Early Hints
Link: </hero.jpg>; rel=preload; as=image

HTTP/1.1 200 OK
Content-Type: text/html
...

This starts the image download while the server generates the HTML.

Add preloads via HTTP header:

Link: </hero.jpg>; rel=preload; as=image

Useful for:

  • Dynamic pages where you can’t easily modify HTML
  • CDN-level optimization
  • A/B testing preload strategies

Framework Integration

Next.js

import Head from 'next/head';
import Image from 'next/image';

export default function Page() {
  return (
    <>
      <Head>
        <link
          rel="preload"
          as="image"
          href="/_next/image?url=%2Fhero.jpg&w=1200&q=75"
        />
      </Head>
      <Image
        src="/hero.jpg"
        width={1200}
        height={600}
        alt="Hero"
        priority // Adds fetchpriority="high"
      />
    </>
  );
}

Note: Next.js priority prop handles preloading automatically in many cases.

Nuxt.js

<script setup>
useHead({
  link: [
    {
      rel: 'preload',
      as: 'image',
      href: '/hero.jpg'
    }
  ]
});
</script>

<template>
  <NuxtImg src="/hero.jpg" fetchpriority="high" alt="Hero" />
</template>

Astro

---
// Generate preload link for responsive images
const heroSrcset = [
  { width: 600, src: '/hero-600.jpg' },
  { width: 900, src: '/hero-900.jpg' },
  { width: 1200, src: '/hero-1200.jpg' }
];
---

<html>
  <head>
    <link
      rel="preload"
      as="image"
      href="/hero-1200.jpg"
      imagesrcset={heroSrcset.map(s => `${s.src} ${s.width}w`).join(', ')}
      imagesizes="100vw"
    />
  </head>
  <body>
    <img
      src="/hero-1200.jpg"
      srcset={heroSrcset.map(s => `${s.src} ${s.width}w`).join(', ')}
      sizes="100vw"
      alt="Hero"
      fetchpriority="high"
    />
  </body>
</html>

Common Mistakes

Mistake 1: Preloading Without as=“image”

<!-- WRONG: Missing as attribute -->
<link rel="preload" href="hero.jpg">

<!-- CORRECT -->
<link rel="preload" as="image" href="hero.jpg">

Mistake 2: Preload URL Mismatch

<!-- Preload URL -->
<link rel="preload" as="image" href="hero.jpg">

<!-- Different URL used - preload wasted! -->
<img src="./hero.jpg" alt="Hero">

URLs must match exactly, including protocol, domain, and path.

Mistake 3: Preloading Lazy-Loaded Images

<!-- WRONG: Conflicts with lazy loading -->
<link rel="preload" as="image" href="below-fold.jpg">
<img src="below-fold.jpg" loading="lazy" alt="Content">

<!-- CORRECT: Don't preload lazy images -->
<img src="below-fold.jpg" loading="lazy" alt="Content">

Mistake 4: Missing type for Modern Formats

<!-- WRONG: Browser may preload unsupported format -->
<link rel="preload" as="image" href="hero.avif">

<!-- CORRECT: Browser can skip if unsupported -->
<link rel="preload" as="image" href="hero.avif" type="image/avif">

Mistake 5: Too Many Preloads

<!-- WRONG: Diminishes benefit -->
<link rel="preload" as="image" href="image-1.jpg">
<link rel="preload" as="image" href="image-2.jpg">
<link rel="preload" as="image" href="image-3.jpg">
<link rel="preload" as="image" href="image-4.jpg">
<link rel="preload" as="image" href="image-5.jpg">

Preload only 1-3 critical images.

Mistake 6: Unused Preloads

Chrome warns about preloads not used within 3 seconds:

The resource was preloaded using link preload but not used within a few seconds from the window's load event.

Ensure preloaded resources are actually used.

Summary

Quick Reference

ScenarioApproach
Hero/LCP imagePreload + fetchpriority=“high”
Responsive LCPPreload with imagesrcset/imagesizes
Modern format LCPPreload with type attribute
CSS background (critical)Preload
External CDN imagesPreconnect + Preload
Below-fold imagesNo preload, use lazy loading

Checklist

  1. ✅ Preload your LCP image
  2. ✅ Use fetchpriority="high" on LCP images
  3. ✅ Include type attribute for AVIF/WebP preloads
  4. ✅ Match preload URLs exactly with image URLs
  5. ✅ Use imagesrcset/imagesizes for responsive preloads
  6. ✅ Preconnect to external image CDNs
  7. ✅ Limit preloads to 1-3 critical images
  8. ✅ Don’t preload lazy-loaded images
  9. ✅ Verify preloads are used (no browser warnings)
  10. ✅ Measure LCP improvement

Preloading and priority hints are precision tools. Used correctly on your most critical images, they can significantly improve LCP. Overused, they waste bandwidth and hurt performance.

Ready to optimize your images?

Sirv automatically optimizes, resizes, and converts your images. Try it free.

Start Free Trial