skip to content

In Angular's NgOptimizedImage, how is srcset generated for a fixed-size image versus one with a sizes attribute?

level: middleimportance: should knowfreq 30%

answer

  1. loader required first
  2. no sizes: density descriptors
  3. sizes: width breakpoints
  4. auto prepended for lazy images

basics

~20 s

With a loader configured, Angular's NgOptimizedImage builds a 1x/2x density srcset from width when there is no sizes attribute, and a width-descriptor srcset from IMAGE_CONFIG breakpoints when sizes is set. ngSrcset or disableOptimizedSrcset override it.

solid answer

~40 s

Automatic `srcset` needs a real loader, because each entry is a loader call with a different width. Without `sizes`, the directive treats the image as fixed-size and emits two density candidates — the loader URL at `width` for `1x` and at twice `width` for `2x` — unless the image is larger than 1920×1080, where it emits none. With `sizes`, it treats the image as responsive and emits one `w` candidate per breakpoint from `IMAGE_CONFIG` (default 16 to 3840 px); for exactly `sizes="100vw"` it keeps only breakpoints of 640 and above. For lazy images it writes `sizes` as `auto, <yours>`, which browsers that support `sizes=auto` use for a more accurate pick. `ngSrcset="400w, 800w"` supplies your own descriptors, and `disableOptimizedSrcset` turns generation off.

code

html · 7 lines
html
<img ngSrc="avatars/ana.jpg" width="96" height="96" alt="Ana" />

<img ngSrc="posts/cover.jpg" width="1200" height="675"
     sizes="(max-width: 768px) 100vw, 50vw" alt="Post cover" />

<img ngSrc="posts/diagram.png" width="1600" height="900"
     ngSrcset="480w, 960w, 1600w" sizes="80vw" alt="Diagram" />

go deeper

for a junior

Recall that NgOptimizedImage can generate srcset for you once a loader is configured.

for a middle

Explain density versus width descriptors, when each is generated, and how sizes, breakpoints and ngSrcset change the result.

for a senior

Audit real srcset output in the DOM, tune IMAGE_CONFIG breakpoints to your layout, and fix missing sizes on responsive images.

for a principal

Align breakpoints with the image service's cached variants so every generated width is a cache hit.

## Why srcset matters here A `srcset` lists alternative URLs for one image so the browser can download the smallest file that still looks sharp. **`NgOptimizedImage`** builds it for you — but only when it can produce different URLs, which requires an **image loader** (`IMAGE_LOADER` or a built-in loader provider). With the default loader, no `srcset` is generated. ## Fixed-size images: no `sizes` If the image has no `sizes` attribute, the directive assumes it renders at the size given by `width` and `height`. It generates **density descriptors**: ```html <!-- ngSrc="avatars/ana.jpg" width="96" height="96" --> <img srcset="https://img.example.com/avatars/ana.jpg?w=96 1x, https://img.example.com/avatars/ana.jpg?w=192 2x" ...> ``` - Multipliers are **1x and 2x**, calling the loader with `width` and `2 × width`. - If `width` is over **1920** or `height` over **1080** and there is no `sizes`, no srcset is generated; the image is treated as too large for a fixed-size ladder. ## Responsive images: with `sizes` With `sizes`, the directive switches to **width descriptors** based on the breakpoint list in **`IMAGE_CONFIG`**: - Default breakpoints: `16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840`. - One entry per breakpoint: the loader URL at that width, followed by `640w`, `750w` and so on. - When `sizes` is exactly **`100vw`**, breakpoints below **640** are dropped, since a full-viewport image is never that narrow. - `fill` images with no `sizes` get `100vw` by default. Custom breakpoints: ```ts { provide: IMAGE_CONFIG, useValue: { breakpoints: [384, 640, 828, 1200, 1920] } } ``` ## The `auto` prefix For images that end up **`loading="lazy"`**, the directive writes `sizes` as `auto, <your value>` (and `auto, 100vw` for a width-descriptor `ngSrcset` without `sizes`). Browsers that support `sizes="auto"` then use the element's actual laid-out width; others ignore `auto` and use the rest. Priority images keep your `sizes` value as written, because `auto` only applies to lazy images. ## Overriding generation | Want | Use | |---|---| | your own list of widths or densities | `ngSrcset="320w, 640w, 1280w"` or `ngSrcset="1x, 2x, 3x"` | | no srcset for one image | `disableOptimizedSrcset` | | a hand-written `srcset` | not with the directive: combining `srcset` with `ngSrcset` is rejected in development | `ngSrcset` contains only descriptors, never file names; the directive calls the loader for each. Density descriptors are capped: above **3x** is an error, and the directive recommends staying at or below **2x**. ## Writing `sizes` well `sizes` describes the rendered width in CSS terms, such as `(max-width: 768px) 100vw, 50vw` for a one-column/two-column layout. It is the directive's only clue that an image is responsive; leaving it off a full-width image produces a 1x/2x pair at the `width` you gave, which may be much too small or large for the actual screen.

  • Why does a 2400x1600 image with no sizes attribute get no srcset?
    Without `sizes`, the directive would build a fixed-size 1x/2x ladder from `width`. Above 1920 wide or 1080 tall, it skips that because a 2x version of such an image is rarely what a fixed-size slot needs. Add a `sizes` value so it generates width descriptors from the breakpoints instead.
  • Why do only lazy images get sizes=auto prepended?
    `sizes="auto"` lets the browser use the element's laid-out width, which is only known after layout. Lazy images are fetched after layout, so the value is usable; eager images are requested earlier, so the directive keeps the explicit `sizes` you wrote.

saying these in an interview costs you the question

  • NgOptimizedImage generates srcset even with the default loader.
  • Without sizes, the directive emits the full breakpoint list.
  • The directive prepends auto to sizes on every image.
  • ngSrcset should list full image URLs.
  • 3x and 4x densities are recommended for sharpness.