In Angular, what does NgOptimizedImage do when you replace an img's src with ngSrc, and why must you give width and height?
answer
- directive from @angular/common
- attribute sets on the img
- lazy unless marked priority
- space reserved, or fill a parent
basics
~20 sAngular's NgOptimizedImage takes over an img tagged with ngSrc: it sets loading, fetchpriority and decoding, builds src and srcset through a loader, and runs dev checks. width and height are required, or fill, so the browser reserves space and avoids layout shift.
solid answer
~40 s`NgOptimizedImage` comes from `@angular/common` and activates on `<img ngSrc="…">`. It writes the real attributes itself: `loading="lazy"` by default for images not marked `priority`, `fetchpriority`, `decoding`, and then `src` and `srcset`, both produced by the configured image loader. `ngSrc` exists instead of `src` so the browser does not start downloading before the directive has set `loading`; using `src` alongside `ngSrc` is an error. `width` and `height` are required — the directive throws without them — because they let the browser reserve the box before the file arrives, which prevents layout shift. For a fixed-size image they are the rendered size; for a responsive one, the file's intrinsic size, with the same aspect ratio. When you do not know the size, use `fill`: the image fills its positioned parent, and you set no width or height.
code
ts · 17 linesimport { Component } from '@angular/core';
import { NgOptimizedImage } from '@angular/common';
@Component({
selector: 'app-product-card',
imports: [NgOptimizedImage],
styles: `.banner { position: relative; height: 240px; }
.banner img { object-fit: cover; }`,
template: `
<img ngSrc="products/lamp.jpg" width="400" height="300" alt="Desk lamp" />
<div class="banner">
<img ngSrc="banners/spring.jpg" fill alt="" />
</div>
`,
})
export class ProductCard {}go deeper
Remember ngSrc, the required width and height or fill, and that non-priority images are lazy by default.
Explain why ngSrc exists, what attributes the directive writes, and how width and height differ for fixed and responsive images.
Use fill for unknown sizes and background-style images, and treat the development errors as a checklist for layout-shift bugs.
Make NgOptimizedImage the default for content images across teams, with a lint or review rule against bare src.
## What the directive is **`NgOptimizedImage`** is a standalone directive in `@angular/common` (stable since v15) that applies image-loading best practices to a normal `<img>` element. You import it into a component's `imports` array and switch the image from `src` to **`ngSrc`**: ```html <img ngSrc="products/lamp.jpg" width="400" height="300" alt="Desk lamp" /> ``` The directive then owns the attributes that decide how the browser fetches the image. ## What it sets on the `<img>` | Attribute | Default image | Image marked `priority` | |---|---|---| | `loading` | `lazy` (or the value you pass in `loading`) | `eager` | | `fetchpriority` | `auto` | `high` | | `decoding` | `auto` (or the value you pass) | `sync` | | `src` | the loader's URL for `ngSrc` | same | | `srcset` | generated, if a loader is configured | same | It also adds an `ng-img` marker attribute, and in development runs a set of checks (dimensions, distortion, LCP, preconnect) that log warnings or errors. ## Why `ngSrc` and not `src` The browser starts fetching an image as soon as it sees a `src` attribute. If the directive only rewrote `loading` after that, lazy loading would come too late. With `ngSrc`, the directive sets `loading`, `fetchpriority` and `decoding` **first** and writes `src` and `srcset` **last**. Setting both `src` and `ngSrc` on the same element is rejected in development (**NG02950**). ## Why `width` and `height` are required - The browser uses them to compute the **aspect ratio** and reserve space before the file downloads, so content below does not jump (layout shift). - Without them, the directive throws **NG02954** ("required attributes are missing"), suggesting `width`/`height` or `fill`. - For a **fixed-size** image, use the rendered size in CSS pixels. - For a **responsive** image (styled to grow and shrink), use the file's **intrinsic** size; CSS such as `width: 100%; height: auto` then scales it, and the ratio still reserves space. - In every case the ratio must match the file; if it does not, a development warning tells you. ## `fill` mode When the size is not known, or the image should behave like a background: ```html <div class="banner"> <img ngSrc="banners/spring.jpg" fill alt="" /> </div> ``` - `fill` makes the image cover its parent; **do not** set `width` or `height` (the directive reports an error if you do). - The parent must be positioned: `position: relative`, `fixed` or `absolute`. - Use `object-fit: cover` or `contain` and `object-position` to control cropping. - A `fill` image defaults `sizes` to `100vw` if you give none, which drives srcset selection. ## What it does not do on its own - Without a configured **loader**, the default loader returns `ngSrc` unchanged, so no automatic `srcset` is generated. - It does not convert formats or compress files; that is the image service's job. - It does not work on CSS `background-image`; migrate to a child `<img ngSrc … fill>` instead. - It is not a replacement for `@defer`; it controls how an image loads, not when a component is created.
- What do width and height mean for a responsive image styled with width: 100%?They should be the file's intrinsic pixel size. CSS then scales the element, and the browser keeps the aspect ratio from the attributes to reserve space. What matters is that the ratio matches the file; the absolute numbers are not the rendered size for responsive images.
- Why must a fill image's parent be positioned?A `fill` image is absolutely positioned to cover its container. Absolute positioning is resolved against the nearest positioned ancestor, so the parent needs `position: relative`, `fixed` or `absolute`; otherwise the image sizes itself against some other ancestor and fills the wrong box.
saying these in an interview costs you the question
- NgOptimizedImage works with a plain src attribute.
- width and height must always be the rendered CSS size.
- fill mode still needs width and height.
- Every NgOptimizedImage image loads eagerly unless you add loading=lazy.
- The directive compresses and converts images to WebP.