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

For a basic image, place the file in your Angular workspace’s public/ directory and use a normal <img src="/file.jpg">. For a URL held in component state, bind [src]. For production images that need responsive sizing, lazy loading, and layout-shift protection, import NgOptimizedImage and use ngSrc with dimensions (or fill). This guide shows each pattern, explains the asset configuration behind it, and provides fixes for images that do not load.

Choose the right Angular image pattern

Need Use What you must provide
One local, fixed image Native <img src> A file emitted from public/ or the configured assets directory
URL changes at runtime [src]="url" A string in component state and a valid URL
Performance-conscious production image NgOptimizedImage with ngSrc width and height, or fill; add sizes when responsive
Images transformed by a CDN NgOptimizedImage plus an image loader A configured provider loader or a custom loader that handles requested widths

Display a local image from the public folder

Angular workspaces serve files in public/ as static files during development and copy them as-is into a production build. Create this layout:

your-app/
├── public/
│   └── logo.png
└── src/

Reference the file from a component template with a root-relative URL:

<img src="/logo.png" alt="Company logo">

The leading slash means the browser requests the file from the deployed application’s root. Always provide useful alternative text; an empty alt="" is appropriate only for a purely decorative image.

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

Using a configured assets directory

Some projects keep files under a folder such as src/assets. In that case, the application build target must list the folder in its assets array. The emitted path then determines the URL, commonly:

<img src="/assets/logo.png" alt="Company logo">

Open the workspace build configuration and confirm that the file or folder is present in the active build target’s assets setting. A path that exists on disk but is not copied by the build will produce a 404 in the browser.

Bind a dynamic image URL

When the image changes according to a user, API response, route, or other state, use property binding rather than interpolating an HTML attribute.

import {Component} from '@angular/core';

@Component({
  selector: 'app-profile',
  template: `
    <img [src]="photoUrl" alt="Profile photo">
  `,
})
export class ProfileComponent {
  photoUrl = '/images/profile.jpg';
}

Angular updates the element whenever photoUrl changes. The value can also be an absolute HTTPS URL returned by an API. Validate or constrain user-supplied URLs in your application; do not treat arbitrary input as trusted markup.

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

Dynamic URLs with NgOptimizedImage

For optimized loading, import the directive from @angular/common and bind ngSrc:

import {Component} from '@angular/core';
import {NgOptimizedImage} from '@angular/common';

@Component({
  selector: 'app-profile',
  standalone: true,
  imports: [NgOptimizedImage],
  template: `
    <img [ngSrc]="photoUrl"
         width="640"
         height="480"
         alt="Profile photo">
  `,
})
export class ProfileComponent {
  photoUrl = '/images/profile.jpg';
}

If your application uses NgModules rather than standalone components, make the directive available through the module that declares the component. A missing import is a common cause of template errors when switching from src to ngSrc.

Use NgOptimizedImage for production images

NgOptimizedImage enforces image-loading best practices. It requires intrinsic dimensions for normal images, lazy-loads non-priority images by default, and can generate responsive srcset candidates when a loader is configured.

import {Component} from '@angular/core';
import {NgOptimizedImage} from '@angular/common';

@Component({
  selector: 'app-product-page',
  standalone: true,
  imports: [NgOptimizedImage],
  template: `
    <img ngSrc="hero.jpg"
         width="1600"
         height="900"
         priority
         sizes="100vw"
         alt="Product hero image">

    <img ngSrc="detail.jpg"
         width="800"
         height="600"
         sizes="(max-width: 700px) 100vw, 50vw"
         alt="Product detail">
  `,
})
export class ProductPageComponent {}

Why width and height matter

Set the source image’s intrinsic dimensions, preserving its aspect ratio. The browser can reserve the correct space before the file arrives, preventing content from jumping while loading. If CSS makes the rendered ratio differ from the declared ratio, correct the styling—often with width: auto or height: auto—instead of suppressing the warning.

Free tools Windows power users keep installed

One-click scans. No signup required.

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

Responsive images and the sizes attribute

For an image that spans the viewport, use sizes="100vw". For a two-column layout, a value such as sizes="(max-width: 700px) 100vw, 50vw" tells the browser that the image occupies the full viewport on small screens and roughly half on larger screens. Without a meaningful sizes value, the browser may choose an unnecessarily large candidate. Width-aware srcset generation is most useful when the configured loader can request those widths from your image service.

Fill mode for container-based layouts

Use fill mode when the image should occupy a positioned parent rather than have fixed dimensions. The parent must establish a size and positioning context:

<div class="hero-frame">
  <img ngSrc="hero.jpg" fill priority alt="Product hero">
</div>
.hero-frame {
  position: relative;
  min-height: 320px;
}
.hero-frame img {
  object-fit: cover;
}

Do not combine fill with a parent that has no height; the resulting zero-size box can make the image appear missing.

Lazy loading and the LCP image

Non-priority NgOptimizedImage images use lazy loading by default. Mark the image likely to be the page’s Largest Contentful Paint element with priority. Angular then applies eager loading and high fetch priority and may emit a preload hint during server rendering. Usually that is the above-the-fold hero, not every image on the page. Making every image priority competes for bandwidth and removes the benefit of lazy loading.

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

Do not guess at a performance percentage. Measure your own application with browser network traces and Core Web Vitals, because layout, device, cache state, and image service all affect the result.

Configure an image loader or CDN

The generic loader leaves the source URL unchanged. Angular documents preconfigured loaders for Cloudflare Image Resizing, Cloudinary, ImageKit, Imgix, and Netlify. A loader can construct transformation URLs and produce width-specific candidates.

When your provider is not supported

Use a custom loader. Angular supplies an ImageLoaderConfig containing src and optional width, height, and loaderParams. Your loader should use the requested width whenever it is present; otherwise generated srcset entries will not actually request different image sizes. Keep the origin and transformation rules consistent with the URLs your service accepts.

Complete implementation checklist

  1. Put local files in public/, or add the chosen folder to the active build target’s assets array.
  2. Use a root-relative emitted URL such as /logo.png or /assets/logo.png.
  3. Use [src] for a changing URL, or import NgOptimizedImage and use [ngSrc].
  4. Provide descriptive alt text and preserve the source aspect ratio.
  5. With ngSrc, provide width and height, or use fill inside a correctly sized positioned parent.
  6. Add sizes whenever the rendered width changes with the layout.
  7. Mark only the LCP or otherwise critical above-the-fold image priority.
  8. Configure a matching CDN loader if you need width-aware transformations and srcset.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Troubleshoot an Angular image that will not load

The request is 404

Inspect the browser’s Network panel and copy the exact requested URL. Check capitalization, leading slashes, and whether the file is under public/ or an assets folder actually listed in the build configuration. A file at public/images/a.png is requested as /images/a.png, not /public/images/a.png.

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

NgOptimizedImage reports a template or directive error

Import NgOptimizedImage in the standalone component’s imports, or expose it through the NgModule that owns the component. Then confirm the attribute is ngSrc, not a mixture of src and ngSrc bindings.

Angular complains about missing dimensions

Add numeric width and height that match the source ratio, or switch to fill and give the parent a definite size and position: relative.

The image is stretched or distorted

Compare the declared dimensions, CSS dimensions, and the source file’s ratio. Use height: auto, width: auto, or an intentional object-fit rule. Do not silence the warning while leaving conflicting geometry in place.

The wrong responsive candidate is downloaded

Set sizes to describe the actual layout share. If a CDN is involved, verify that its loader is configured and that it honors the requested width; a custom loader that ignores width cannot provide useful responsive candidates.

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

The hero image loads late

Apply priority to the likely LCP image and remove it from below-the-fold images. Check for a slow image origin, redirects, or an oversized source in the Network panel before changing other settings.

Generating screenshots of Angular pages

If you need an image of a rendered Angular route for documentation, previews, or visual checks, a screenshot service avoids maintaining a headless-browser job. ScreenshotNeo is the first option to try: it removes cookie banners, popups, and chat widgets before capture, bills only clean successful shots, and starts at the lowest paid plan described here.

Or skip the browser setup

Call the API after the route is deployed. The response can be PNG, JPEG, WebP, or PDF according to the request options.

curl -G "https://api.screenshotneo.com/v1/shot" 
  -d access_key=YOUR_API_KEY 
  --data-urlencode url=https://your-angular-site.example/products 
  -o shot.webp

Python:

import requests

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://your-angular-site.example/products"},
    timeout=90,
)
open("shot.webp", "wb").write(r.content)

Node.js:

const q = new URLSearchParams({
  access_key: 'YOUR_API_KEY',
  url: 'https://your-angular-site.example/products'
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
const image = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('shot.webp', image));

See the ScreenshotNeo documentation for options such as full-page capture, waiting for a selector or network idle, custom CSS and JavaScript, viewport and device settings, dark mode, hiding selectors, and PDF output. Cookie banners, newsletter popups, and chat widgets are removed before the shot; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed, with the outcome exposed in response headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The Free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000. Create a free ScreenshotNeo account.

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

FAQ

Frequently Asked Questions

Should I keep images in src or public?

Use public (or a folder listed in the build target’s assets array) when the file should be served as-is. The important requirement is that the folder is copied into the build and that your template uses the resulting emitted URL.

Can NgOptimizedImage display an external URL?

Yes. Bind the external URL with ngSrc, provide dimensions or fill mode, and configure an appropriate image loader when you need CDN-generated responsive candidates.

How many Angular images should be marked priority?

Normally only the image expected to be the page’s LCP element or another genuinely critical above-the-fold image. Leave the rest lazy unless measurement shows a specific reason.

Why does a screenshot service need a deployed URL?

A remote screenshot API captures what a browser can reach. Deploy the Angular route first, or expose a reachable preview environment; a localhost URL on your own machine is not generally available to the service.

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

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.