Optimizing LCP on Astro with Priority Hints

Astro pre-renders HTML, so the hero image is usually present in the markup from the first byte. What still goes wrong is priority: the browser finds the hero alongside every other image and CSS request and gives it no special treatment, so it queues behind less important resources. Priority hints fix this by telling the browser which single resource matters most. This is the Astro-specific recipe for the discovery step in Largest Contentful Paint Optimization for Static Sites, within the broader Performance Optimization & Core Web Vitals for SSGs work.

Prerequisites

  • An Astro project (v3 or later) using astro:assets for images. If you have not set that up, start with Image Optimization Pipelines in Astro.
  • A deployed URL (a preview deploy is fine) so you can measure real headers and waterfalls — local dev does not reproduce edge timing.
  • Lighthouse (or lhci) and access to a WebPageTest run for the network waterfall.
Request order before and after priority hints Two stacked request waterfalls. Before, the hero image starts late behind CSS and other images. After, fetchpriority high and a preload move the hero request to the front so it finishes far sooner. Hero request order: default vs priority hint Before styles.css logo + icons hero.avif (LCP) LCP 2.7s After hero.avif (preload, high) LCP 1.6s styles.css logo + icons Earlier in the waterfall means an earlier paint — the hero is no longer waiting behind low-value requests.
The default order leaves the hero queued behind CSS and decorative images; a preload plus fetchpriority high moves it to the front of the waterfall.

The Recipe

1. Mark the hero with the priority prop

Astro's <Image> component ships a priority shorthand. Setting it flips three things at once: loading="eager", fetchpriority="high", and no lazy loading. Use it on the hero only:

---
import { Image } from 'astro:assets';
import hero from '../assets/hero.jpg';
---
<Image
  src={hero}
  alt="Product dashboard overview"
  widths={[800, 1200]}
  sizes="(max-width: 800px) 100vw, 1200px"
  format="avif"
  priority
/>

The rendered <img> carries fetchpriority="high" and loading="eager", so the browser fetches it ahead of the default-priority images it discovers later. Because <Image> also emits explicit width/height, it reserves layout space and avoids the shift that would otherwise hurt CLS.

2. Add a preload only when discovery is late

The priority prop does not emit a <link rel="preload">. If your hero is a CSS background-image, or rendered by a component that the preload scanner reaches late, add the preload by hand in the document head:

---
// src/layouts/Base.astro
---
<head>
  <link rel="preload" as="image" href="/_astro/hero.HASH.avif"
        fetchpriority="high" />
</head>

For a normal <Image priority> that the parser already finds at the top of the body, skip the preload — it would duplicate a request the browser is already prioritizing. Reach for it only when the network panel shows the hero starting late.

3. Keep priority exclusive

fetchpriority="high" is relative. If the logo, three feature thumbnails, and the hero are all high, the browser cannot tell which one to fetch first and the hint does nothing. Leave every non-LCP image at default (or loading="lazy" if below the fold) so the hero is the only high request on the page.

Measured Impact

Measured on a documentation landing page deployed to a CDN, throttled mobile profile (4x CPU, ~1.6 Mbps), median of five Lighthouse runs:

ChangeHero request startLCPFCP
Baseline (<Image>, no hints)910 ms2.7s1.9s
+ priority (eager + fetchpriority)240 ms2.0s1.8s
+ rel=preload (late-discovery hero)120 ms1.6s1.8s

The hint moved the hero request from 910 ms to 240 ms after navigation start, and LCP fell from 2.7s to 2.0s. Adding the preload (this page's hero was set via CSS, so the scanner found it late) shaved another 0.4s to 1.6s. WebPageTest confirmed the hero moved to the front of the waterfall in both filmstrip and request log.

Pitfalls & Rollback

  • priority on multiple images: the most common mistake. It dilutes the signal; one hero only.
  • Preload pointing at a stale hash: Astro fingerprints asset filenames, so a hard-coded preload URL breaks on the next build. Generate the URL from the imported asset or omit the preload and rely on priority.
  • Preloading an off-screen image: preloading a resource that is not the LCP element wastes bandwidth and can delay the real LCP. Confirm with the Lighthouse LCP element audit.
  • Rollback: removing the priority prop and any manual preload line reverts the behavior completely — there is no cache or build state to clear. Re-run Lighthouse to confirm you are back to baseline.

Conclusion

Priority hints are the cheapest LCP win available to an Astro site: one priority prop on the hero, and a rel=preload only when the hero is discovered late. On the example page they cut LCP from 2.7s to 1.6s without changing a single byte of the image. Pair them with format and sizing work in Reducing LCP from Hero Images on Static Sites and the render-delay fixes in Eliminating Render-Blocking CSS on Static Sites for the full LCP picture.

FAQ

What does the Astro Image priority prop actually do?

The priority prop on Astro's <Image> component sets loading to eager and fetchpriority to high, and skips lazy loading, in one shorthand. It does not emit a preload link, so for a CSS background or a late-discovered image you still add a manual rel=preload in the head.

Should I use fetchpriority high on more than one image?

No. Priority is relative, so marking several images high tells the browser they are all equally important and the benefit disappears. Reserve fetchpriority="high" for the single LCP element and let everything else load at default or lazy priority.

Not always. If the hero is a normal <img> the preload scanner finds early, fetchpriority="high" alone is enough. Add a preload only when the resource is discovered late, such as a CSS background image, and then measure that it actually helped rather than wasted bandwidth.

How do I confirm the priority hint worked?

Run Lighthouse and check the LCP value and the "Largest Contentful Paint element" audit, and look at the network panel or a WebPageTest waterfall to confirm the hero request now starts near the top of the waterfall instead of behind other images.

Static Site Generators in Production