Before you add any hint of your own, what does a browser use to decide a request's priority — and why does an image inside the initial viewport not automatically download ahead of one far below the fold?
answer
- type dominates, position refines
- nothing paints without CSS
- images start at the bottom
- the browser cannot see the viewport yet
- the correction arrives after layout
basics
~20 sBrowsers rank a request first by resource type — render-blocking CSS and blocking scripts at the top, fonts high, images and async scripts low — and only afterwards by position. Viewport position is applied late, because the browser cannot know an image is visible until layout has run.
solid answer
~50 sThe initial ranking is made at request time, from information available in the markup: what kind of resource this is, and where the reference sits. Render-blocking stylesheets rank at the very top, blocking scripts just below, fonts needed for visible text high, and images and `async` scripts low — nothing waits on them to paint. Position refines within a type, not across types. The viewport question is the interesting part: at the moment an `<img>` is discovered there is no layout yet, so the browser genuinely does not know whether it is on screen. In Chromium as of 2025 it starts images low and *boosts* a small number of them once layout tells it they are in the initial viewport. That boost is real but late — the request may already have been sitting behind a queue of other work. That gap between "discovered" and "known to be visible" is exactly the window an explicit priority signal closes.
code
html · 7 lines<!-- Both images are ranked low at discovery time: no layout has run yet,
so the browser cannot tell which one the user will actually see. -->
<img src="/footer-badges.png" width="320" height="64" alt="">
<section class="hero">
<img src="/hero-2000w.jpg" width="2000" height="1000" alt="Product on a desk">
</section>go deeper
Know the ordering by resource type: render-blocking CSS at the top, blocking scripts next, images and async scripts near the bottom. Say plainly that images are ranked low by default.
Explain why the viewport cannot be an input at request time — layout has not run — and describe the after-layout boost for in-viewport images, including that it is late and capped.
Demonstrate that you look for mismatches between a resource's type and its actual importance in both directions, and that you check the real ranking on a throttled load rather than assuming it.
Own the fact that these rules are engine- and version-specific. Decide what your team's guidance depends on: the durable shape of the model, not one browser build's internal levels.
## Two inputs, applied in order The browser's default priority model is simpler than people expect. It answers two questions about each request, in this order. **What kind of resource is this?** This is the dominant input, because resource type is a good proxy for "does the first paint wait on it". Roughly, from most to least urgent: - A render-blocking stylesheet — nothing paints until it arrives, so it sits at the top. - A parser-blocking script — the parser is stopped until it arrives and runs. - A font needed to draw text that is about to appear. - The page's own data fetches, which usually sit somewhere in the middle. - Images, `async`/`defer` scripts, prefetched things for a future navigation, and beacons — all low, because nothing on screen is waiting on them at the moment they are discovered. **Where and what is it for?** Position and context refine the ranking *within* a type rather than across types. A stylesheet in the head is treated differently from one pulled in later; a script marked `async` is demoted relative to a blocking one because the developer has explicitly said the parser need not wait. Chromium exposes the result as a small set of internal levels and shows the chosen level per request in its network tooling. The exact level names and the precise rules differ between engines and change between versions, so the useful thing to carry is the *shape*: type first, position second, and images near the bottom by default. ## Why the viewport does not settle it Here is the part that trips people up. Being in the initial viewport is the single best predictor that an image matters — and it is precisely the thing the browser cannot know when it issues the request. The sequence is: 1. The preload scanner or parser finds `<img src="hero.jpg">` in the byte stream. 2. It must decide a priority *now*, before the request goes out. 3. At that moment, no layout has run. The CSS may not even have arrived. Whether that image is a full-bleed hero or a footer badge is unknowable. So the browser makes the statistically safe choice — images start low — and corrects later. In Chromium as of 2025, once the first layout tells the engine which images fall inside the initial viewport, it raises a limited number of them. Two properties of that correction matter: - **It is late.** Layout happens after the CSS has arrived and been parsed. By then a low-ranked hero request may have been queued behind a dozen other things for hundreds of milliseconds. - **It is capped.** The boost is not applied to every visible image, so a viewport packed with images does not all get promoted. That is the whole reason an explicit priority signal exists on the platform: it lets you state at *markup* time what the browser can otherwise only discover at *layout* time. ## Why the below-the-fold image can win If two images are both ranked low, the tiebreak falls back to ordinary factors — which was discovered first, which connection was free, how big each response is. A below-the-fold image referenced earlier in the document, or one served from an already-warm connection, can easily complete before an in-viewport image discovered later. Nothing in the default model prevents it, because at request time both were just "an image". ```html <img src="/logo-strip.png" alt=""> <!-- offscreen, but discovered first --> <section class="hero"> <img src="/hero-2000w.jpg" alt=""> <!-- in view, but larger and later --> </section> ``` Both start low. The first can be done before the second has climbed out of the queue. ## What this implies for strategy Three practical consequences follow from the model. **Look for the type/importance mismatch.** The defaults are wrong exactly where a resource's *type* disagrees with its *importance*: an image that is the main content, a font for text that appears immediately, a data fetch that gates the first render. Those are your promotion candidates, and there are usually one or two per page. **Look for the reverse mismatch too.** Things the type-based model ranks respectably but you know are not urgent — an above-the-fold decorative image, a script-issued fetch for content the user has not scrolled to, a third-party request that is high because of how it is loaded. Demoting these is often the cheaper win, because it frees the pipe without you having to argue about which resource is *most* important. **Don't fight the defaults where they are right.** The type model already ranks blocking CSS and blocking scripts correctly. Adding a signal there changes nothing and costs you a line of markup a future reader must reason about. Finally, treat the specifics as version-bound. Ranking rules, the image boost, and the internal level names have all changed over time and vary by engine. Reasoning that depends on the exact level of a given resource type in a given browser build is brittle; reasoning that depends on "images start low and the viewport correction arrives after layout" has held up well.
- If the browser eventually boosts in-viewport images anyway, why bother stating the priority yourself?Because the boost lands after layout, and layout waits on the CSS. For an image that is the page's main content, those hundreds of milliseconds are the whole problem you were trying to fix. Stating it in the markup moves the decision to discovery time, before the request is ever queued behind lower-value work. It also sidesteps the cap on how many visible images get boosted.
- Where in this model does a script-issued fetch sit, and why is that awkward?A fetch issued from JavaScript is ranked when it is made, which is already late — the script had to download and run first. Its type gives it a respectable default rank, but that says nothing about whether the page is actually waiting on it. Both directions are common: a gating fetch that deserves promotion, and background prefetching that deserves demotion.
- You add a priority signal to a render-blocking stylesheet in the head. What changes?Essentially nothing. Blocking CSS already sits at the top of the default ranking, so restating it cannot move it up and there is nothing above it to overtake. It is a no-op line that a future reader will have to investigate before concluding it is safe to delete — a small but real cost.
saying these in an interview costs you the question
- Assumes the browser knows which images are on screen when it requests them
- Thinks source order is the main input to the default ranking
- Believes an in-viewport image is always fetched before an offscreen one
- Says images are ranked low because they are large files
- Treats one browser's internal priority level names as a cross-engine fact