Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

To optimize an image in Angular, import NgOptimizedImage from @angular/common, change the image’s src attribute to ngSrc, give the image either explicit width and height or the fill attribute, add priority to the image most likely to be the page’s Largest Contentful Paint (LCP) element, and set sizes when the image’s rendered width changes with the layout. Those steps cover most of what the directive does. The rest of this guide explains each choice, the trade-offs between them, and where a image CDN loader fits.

What NgOptimizedImage does and does not do

NgOptimizedImage is a template directive that Angular’s own image optimization guide describes as opt-in. You apply it to an <img> element, and it takes over how the browser discovers and loads that image. It does not edit, compress, or resize files in your project. Image size and format still come from the files you ship or from the image service you connect. The directive manages loading behavior, reserves layout space, and, when a loader is configured, builds requests for appropriately sized variants.

The directive also does not apply to CSS background-image declarations. Angular’s guide handles that case with a migration pattern covered in its own section below.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The reference material is at the Angular image optimization guide and the NgOptimizedImage API reference. Both are currently unversioned pages on angular.dev, so check them against the Angular version your application uses before copying any attribute name or default.

Basic setup

  1. Import the directive into the component that renders the image. For a standalone component, add it to the imports array:

    import { Component } from '@angular/core';
    import { NgOptimizedImage } from '@angular/common';
    
    @Component({
      selector: 'app-product',
      standalone: true,
      imports: [NgOptimizedImage],
      templateUrl: './product.component.html',
    })
    export class ProductComponent {}

    In an NgModule-based application, add NgOptimizedImage to the module’s imports array instead.

  2. Replace src with ngSrc on each image that should use the directive. Angular needs control of the src binding so it can decide when the browser starts downloading the file.

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
    <img ngSrc="/assets/product-card.jpg" width="600" height="400" alt="Walnut desk lamp on a white table">
  3. Provide dimensions or fill. Without one of these, Angular cannot reserve space for the image, and the page can shift when it loads. The next section explains which to use.

  4. Mark the LCP image with priority (covered below).

Images that do not have priority are lazy-loaded by default. Leave ordinary images on that default. Switching them to eager loading without a clear reason gives the browser more competing downloads at page start.

Which image to mark as priority

The guide states: “Always mark the LCP image on your page as priority to prioritize its loading.” In practice, the LCP element is usually the largest visible image or text block in the first viewport, such as a hero banner, a featured product photo, or a page-header image. Mark it like this:

<img ngSrc="/assets/hero.jpg" width="1200" height="600" priority alt="Hikers crossing a ridge at sunrise">

With priority, Angular sets high fetch priority and eager loading. For server-rendered pages, it also generates a preload hint, so the browser can start the request earlier. Reserve it for images that appear above the fold on the page.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

LCP can change with the viewport. A banner that is the largest element on a desktop layout may sit below a text block on a phone, and the phone layout may need a different image. Check the real layouts at the breakpoints your users see instead of assuming one hero image is always the LCP candidate. Angular’s development-mode warnings can also flag missing priority hints, which helps when a template has changed.

Choosing between fixed, responsive, and fill

The three display modes differ in what width and height mean and in where the layout box comes from.

Mode Markup pattern What width and height mean Use when
Fixed size ngSrc with width and height The intended rendered dimensions, with the same aspect ratio as the file The image is always displayed at one size, such as an avatar or logo
Responsive ngSrc with width, height, and sizes The file’s intrinsic dimensions. The rendered width changes with the layout The image scales with its container, such as a content photo in a grid
Fill ngSrc with fill, no width or height Not used. The image fills a positioned parent container The parent controls the box, such as a banner or card with a set height

Fixed-size images

Set width and height to the size the image will display at. If the file’s aspect ratio does not match those values, the image will be distorted or cropped depending on your CSS. Angular can generate a srcset from fixed dimensions, so you do not need sizes for a fixed-size image.

Responsive images

For images whose displayed width changes, the width and height attributes should describe the file’s intrinsic dimensions, not the displayed size. Add sizes to tell Angular which width the browser should expect at each viewport. The value should match your real CSS slot, not an estimate:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<img ngSrc="/assets/article-photo.jpg"
     width="1600"
     height="1067"
     sizes="(max-width: 768px) 100vw, 50vw"
     alt="Potter shaping a clay bowl">

This example means the image fills the full viewport width on screens up to 768 pixels wide and half the viewport width above that. If your CSS gives the image a different width, the candidates Angular generates will not match what the browser actually displays, and the browser may download a file that is larger or smaller than it needs.

Fill mode

Use fill when the parent element should set the image’s box. Omit width and height, make sure the parent is positioned, and control cropping with CSS:

<div class="banner">
  <img ngSrc="/assets/banner.jpg" fill priority alt="Lake at dusk">
</div>
.banner {
  position: relative;
  height: 400px;
}

.banner img {
  object-fit: cover;
}

Use object-fit: cover when the image may be cropped to fill the box. Use object-fit: contain when the whole image must stay visible, with empty space around it.

Responsive srcset candidates

When a loader is configured, or when Angular generates candidates from your dimensions and sizes, it produces a set of image widths. The guide’s default breakpoints are 16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, and 3840 pixels. These are configuration values for width candidates, not measured performance results. Angular selects the candidates that fit the sizes slot and the device, so a precise sizes value matters more than the list itself.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You do not need to write a srcset by hand with these directives. If you need to know exactly which URLs your app generates, inspect the rendered <img> element in the browser’s developer tools after the page loads.

Loaders and image CDNs

The guide states: “An image loader is not required in order to use NgOptimizedImage, but using one with an image CDN enables powerful performance features, including automatic srcsets for your images.” A loader tells Angular how to build the URL for a requested width, and whether the image service can serve that width, format, or quality.

Option Does the URL change? When to choose it
No loader (generic) No. The original URL is used as written Images are small enough to serve as they are, or your server already provides the sizes you need
Built-in service loader Yes. The URL is transformed for the chosen service You use Cloudflare Image Resizing, Cloudinary, ImageKit, Imgix, or Netlify, and want automatic variants
Custom loader Yes, through your own function Your image service is not among the built-in integrations

Each built-in loader expects its own URL conventions. The guide describes how to register each one, and the setup differs by service. Check that your service’s URL format matches what the loader constructs before you rely on it in production.

When the image origin differs from your site’s origin, the browser cannot start the connection until it reaches the image. Angular cannot always infer that origin from a loader, so add a preconnect hint manually when it makes sense:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<link rel="preconnect" href="https://images.example.com">

Use a preconnect hint only for origins that serve images on most page loads. A hint for an origin you rarely use adds an unnecessary connection.

Migrating CSS background images

Because the directive does not act on background-image, the documented route is to move the image into an element. The migration has three steps:

  1. Create a container with position: relative, position: absolute, or position: fixed and the dimensions it should occupy.

  2. Place an <img> inside it with ngSrc and fill.

  3. Move the fit and position rules to the image, using object-fit and object-position, in place of the old background-size and background-position values.

    Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

The result is a real image element with alt text available to assistive technology, which a background image cannot provide. Decorative images can keep an empty alt attribute.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Versions and availability

According to the Angular guide, NgOptimizedImage became stable in Angular 15. It was also backported as stable to Angular 13.4.0 and 14.3.0. If your application is on an earlier version, the directive may be unavailable or behave differently, so confirm the version before copying an example. The guide describes its own current behavior, not the behavior of older releases.

Measuring the result

Angular’s documentation describes the mechanisms and recommended practices for NgOptimizedImage. It does not publish a benchmark of speed or Core Web Vitals gains for any particular application, so a fixed improvement cannot be promised. The effect depends on your source image sizes, responsive layout, which element is the LCP, your CDN, and whether your app is rendered on the server.

To judge the change, measure the same pages before and after with the tools you already use, such as Lighthouse or field data from your analytics, and compare the LCP element and the layout-shift score on each viewport.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshooting common problems

“

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.