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.
PC Slower Than It Used to Be?
A free scan shows the junk files, broken settings and background clutter dragging Windows down - then fixes them in one click.Free scan · Windows 10 & 11Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minute#1 Best Overall
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.
The Tool Desk
Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Dynamic URLs with NgOptimizedImage
For optimized loading, import the directive from @angular/common and bind ngSrc:
Rank #2
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.
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:
Rank #3
<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.
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.
Rank #4
Complete implementation checklist
- Put local files in
public/, or add the chosen folder to the active build target’sassetsarray. - Use a root-relative emitted URL such as
/logo.pngor/assets/logo.png. - Use
[src]for a changing URL, or importNgOptimizedImageand use[ngSrc]. - Provide descriptive
alttext and preserve the source aspect ratio. - With
ngSrc, providewidthandheight, or usefillinside a correctly sized positioned parent. - Add
sizeswhenever the rendered width changes with the layout. - Mark only the LCP or otherwise critical above-the-fold image
priority. - Configure a matching CDN loader if you need width-aware transformations and
srcset.
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.
Recommended Free Tools
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.
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.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Fix the driver behind crashes, sound loss and screen glitches3Clear out junk files and repair common Windows errorsFAQ
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.
Quick Recap
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.

