In HTML, how do fetchpriority="high" on an <img> and a <link rel="preload" as="image"> in the head differ in what they ask the browser to do for a page's main hero image?
answer
- discovery versus urgency
- the scanner already found the img
- priority is a zero-sum budget
- as and crossorigin must match
- the twice-downloaded hero
basics
~20 sfetchpriority="high" raises the urgency of a fetch the browser was going to make anyway; <link rel="preload" as="image"> makes the browser start a fetch it would not otherwise have discovered yet. One reorders, the other discovers earlier.
solid answer
~50 sThey solve different halves of the problem. `fetchpriority="high"` on an `<img>` is a hint about **urgency**: the browser already knows about this image, and you are telling it to schedule the fetch ahead of other, less important requests. That matters because browsers typically start images at a low priority and only raise it once layout proves the image is in the viewport, so the largest visible image spends its first moments queued behind less important work. `<link rel="preload" as="image">` is about **discovery**: it makes the browser request a resource from the head, before the parser reaches the markup that uses it. If the hero `<img>` is already in the initial HTML, the preload scanner finds it almost immediately and `fetchpriority="high"` is the more targeted tool. Preload earns its place when discovery is genuinely late. Combining them is common — a preload can carry `fetchpriority="high"` itself — but a preload whose attributes do not match the element that consumes it downloads the file twice.
code
html · 9 lines<head>
<!-- Only needed when the image is not discoverable from the markup -->
<link rel="preload" as="image" href="/img/hero.jpg" fetchpriority="high">
</head>
<body>
<!-- In the markup: not lazy, sized, and the one image marked urgent -->
<img src="/img/hero.jpg" width="1600" height="900"
fetchpriority="high" alt="Harbour at dusk">
</body>go deeper
Know that fetchpriority="high" marks one image as urgent and that a preload link starts a download early from the head; you are not expected to choose between them under pressure.
Explain the split cleanly: preload fixes late discovery, fetchpriority fixes bad ordering, and the as attribute on a preload sets the destination that makes the response reusable. Note that images start at low priority until layout proves visibility.
Diagnose before prescribing — establish whether the hero is discovered late or merely scheduled late, apply the matching fix, and confirm in the waterfall that the request moved earlier and happened exactly once. Treat blanket high priority as a smell.
Own the guardrails: who may add a preload, how stale ones are found when markup changes, and how the one-high-priority-image rule survives a component library where several teams each believe their image is the important one.
## Two different problems When a hero image arrives late, the cause is one of two things, and the fix differs: 1. **Discovery** — the browser did not know about the resource early enough to request it. 2. **Urgency** — the browser knew, but scheduled it behind other requests. `<link rel="preload">` addresses the first. `fetchpriority` addresses the second. Diagnosing which one you actually have is most of the skill here. ## fetchpriority `fetchpriority` takes `high`, `low`, or `auto` (the default) and appears on `<img>`, `<link>`, and `<script>`, among others. It adjusts the relative priority of a fetch that is going to happen regardless. ```html <img src="/img/hero.jpg" width="1600" height="900" fetchpriority="high" alt="…"> ``` The reason it helps is a scheduling detail worth being able to state: browsers generally cannot tell, at parse time, which images are visible, so images start at a relatively low priority and are boosted only after layout shows they are in the viewport. For the one image that dominates the initial screen, that ordering is backwards, and `fetchpriority="high"` corrects it without waiting for layout. The corollary is that priority is a *relative* signal in a finite budget. Marking every image high is the same as marking none of them high, and it can starve genuinely blocking resources. The honest usage is one image per page — the largest one in the initial viewport — plus, occasionally, `fetchpriority="low"` on things you know are not urgent. ## rel="preload" ```html <link rel="preload" as="image" href="/img/hero.jpg" fetchpriority="high"> ``` This tells the browser: fetch this now, with this destination type, because something later in the page will need it. `as` is not optional cosmetics — it sets the request's destination, which determines the priority the browser assigns and how the response is matched to the eventual consumer. A preload with a wrong or missing `as` commonly results in the file being downloaded twice. For a responsive image, a plain `href` preload would fetch the wrong candidate, so the preload accepts `imagesrcset` and `imagesizes` — the counterparts of the `<img>` element's own candidate attributes — so the preload and the element can agree on which file is wanted. ## When each is the right tool - **Hero `<img>` present in the initial HTML.** The preload scanner finds it almost immediately; the problem is priority, not discovery. Use `fetchpriority="high"` on the element, and make sure nothing has marked it lazy. - **The image is not discoverable from the initial HTML** — referenced from a stylesheet, or added by script after the page loads. Now discovery genuinely is the bottleneck, and a preload in the head is the tool that helps. - **Markup is server-rendered but the image sits deep in the document behind large amounts of content.** Discovery is fast enough with the scanner in most cases; measure before adding a preload. The two are frequently combined, and a preload can carry `fetchpriority="high"` so it is both discovered early and scheduled first. ## The double-download trap A preload only helps if the response it fetches is actually reused by the element that needs it. It is not reused when the two disagree — an `href` that does not match the candidate the `<img>` ends up selecting, missing `imagesrcset`/`imagesizes` for a responsive image, a wrong `as`, or a `crossorigin` mismatch between the preload and the element (this one bites hardest with fonts, but applies to images fetched cross-origin too). The symptom is unmistakable in a network waterfall: the same image, twice. A second trap is the stale preload. Preloads are hand-written in the head and the markup they support changes; a preload for an image the page no longer uses is a wasted download that competes with the ones it does use. Because they are separate from the element, they rot silently. ## The order to apply things For a hero image, the useful ordering is: make sure it is not lazy-loaded, give it intrinsic `width` and `height`, then add `fetchpriority="high"` to the single largest image. Reach for a preload only when you can show the image is discovered late, and verify in the waterfall that it is fetched once, not twice. Everything past that — a decode hint, more preloads — is smaller than those first moves. ## Answers that fall down Saying "just preload it" for an image already sitting in the HTML misses that discovery was never the problem. Saying "mark the images high priority" without the word *one* misses that priority is zero-sum. And a candidate who cannot describe how they would confirm the change — the same request, earlier, and only once — is describing a hope rather than a fix.
- Why does marking several images fetchpriority="high" tend not to help?Priority is relative within a finite connection budget. If everything is high, the browser is back to its own heuristics for ordering, and you may also have pushed genuinely render-blocking resources down the queue. The signal only carries information when it is scarce — in practice one image per page, the largest one in the initial viewport.
- What is the role of the as attribute on a preload link, and what goes wrong without it?`as` declares the request's destination — `image`, `style`, `font`, `script`. It determines the priority the browser assigns and how the response is matched to the element that later needs it. Omit it or get it wrong and the preloaded response is typically not reused, so the resource is fetched a second time, making the page slower rather than faster.
- How would you verify that a preload you added is actually working?Open the network waterfall and check three things: the request starts earlier than before, it appears exactly once rather than twice, and the element that consumes it shows no second fetch. A preload that produces two entries for the same file is a mismatch — usually `as`, `crossorigin`, or a responsive candidate that does not match the element's selection.
- Does fetchpriority="high" rescue an image that also has loading="lazy"?No. They act at different stages: `loading="lazy"` decides whether the request is made yet at all, and priority only orders requests that are being made. A lazy image still waits for layout to place it near the viewport; raising its priority only affects how it is scheduled once that finally happens. Remove the lazy attribute first.
saying these in an interview costs you the question
- Preloads a hero image that is already plain in the initial HTML
- Marks every image fetchpriority="high"
- Omits as on a preload link and expects the response to be reused
- Thinks fetchpriority overrides loading="lazy"
- Believes preload guarantees the resource is used, rather than merely fetched
- Leaves stale preloads in the head after the markup changes