Images are among the heaviest assets on a web page. Loading them all upfront can slow down rendering, increase bandwidth usage, and affect performance metrics like LCP.
If you’re building a fast, modern Angular application where performance matters, you’ll want a way to delay off-screen image loading until needed. Then you might want to use Angular Lazy Load Images.
In this guide, we’ll walk through how to implement and make the most of Angular’s lazy loading for images.

What Is Angular Lazy Load Images?
Angular Lazy Load Images is a performance technique where images are loaded only when they are about to appear in the user’s viewport. This prevents unnecessary downloads during initial page load, especially on pages with many images.
Angular provides native support for this with the NgOptimizedImage directive, introduced in Angular v15 (and backported to 13.4.0 and 14.3.0). Unlike traditional lazy loading, where developers manually manage loading=”lazy” and srcset, this directive automates most of it. It replaces the standard src attribute with ngSrc.
It also enforces best practices such as requiring width and height, warning on potential layout shifts or distortions, and optimizing images with optional CDN loaders.
How to Implement Lazy Loading with NgOptimizedImage?
Follow these core steps to enable lazy loading in Angular using NgOptimizedImage. Each step contributes to optimizing image loading without bloating your app’s performance budget.
Step 1: Import NgOptimizedImage
To begin with, import NgOptimizedImage from @angular/common into your module or standalone component. This will make the directive available for use in templates.
import { NgOptimizedImage } from '@angular/common';
@NgModule({
imports: [NgOptimizedImage],
})
export class AppModule {}
Step 2: Replace src with ngSrc
In your image tags, swap out the standard src attribute with ngSrc. It gives Angular full control over how and when the image is loaded.
<img ngSrc="assets/img/product.jpg" width="400" height="300" />
Step 3: Add Width and Height
As a best practice, always include the width and height attributes. This helps prevent layout shifts during image loading and keeps your layout stable.
<img ngSrc="assets/img/product.jpg" width="400" height="300" />
Step 4: Use the priority Attribute
Add the priority attribute for critical images like banners or hero sections. This ensures the image loads eagerly and improves Largest Contentful Paint (LCP).
<img ngSrc="assets/img/hero.jpg" width="1200" height="600" priority />
Step 5: Use fill for Full-Width or Unknown Sizes
If your image needs to fill its container or you don’t know its width and height, use the fill attribute. The parent element must have a positioned layout (relative, absolute, or fixed).
<img ngSrc="assets/img/bg.jpg" fill />
NgOptimizedImage: Advanced Capabilities You Should Try
Now that you know how to implement NgOptimizedImage in your Angular project, it’s important to understand the features that take it beyond basic lazy loading. These enhancements improve responsiveness, style control, and performance.
Note: The code snippets below are simplified and meant for reference to help understand the core idea.
Placeholder Options and Styling Tips
Adding the placeholder attribute gives your users a smoother visual experience by showing a blurred version of the image while it loads. This reduces the jarring effect of content popping in, especially on slow connections.
<img ngSrc="cat.jpg" width="400" height="200" placeholder />
Responsive Behavior with srcset and sizes
NgOptimizedImage can auto-generate a srcset, allowing browsers to pick the most appropriate image based on screen size and resolution. Adding the sizes attribute tells the browser how much space the image will occupy, ensuring the right image variant is loaded.
<img
ngSrc="hero.jpg"
width="1200"
height="600"
sizes="100vw"
/>
This approach avoids downloading unnecessarily large images on mobile devices while still looking sharp on high-resolution screens.
Image Loaders and CDN Integration
By configuring an image loader, you can offload image resizing and optimization to a CDN like Cloudinary, Imgix, or ImageKit. This not only reduces build size but also ensures device-specific images are served directly from the edge.
providers: [
provideImgixLoader('https://your-cdn.imgix.net'),
],
When using custom loaders, you can pass loaderParams to dynamically control how images are transformed:
<img
ngSrc="profile.jpg"
width="300"
height="300"
[loaderParams]="{ roundedCorners: true }"
/>
This enables advanced features like quality tuning, corner masks, or custom widths without hardcoding multiple image variants.
Migrating from CSS background-image
If your project uses background-image in CSS, NgOptimizedImage with fill mode can replicate the same visual behavior, but with better performance and lazy loading. Start by removing the background style and inserting an image element inside the container.
The fill attribute ensures the image stretches to cover the container, while object-fit: cover lets you maintain aspect ratio just like a background image.
Wrapping Up
NgOptimizedImage goes far beyond lazy loading. From automatic srcset generation to CDN loader integration and smooth placeholder transitions, it’s built to help Angular developers ship fast, responsive, and polished image experiences with minimal effort.
As a best practice, always define explicit width and height (or use fill properly), mark your LCP image with priority, and let Angular handle the rest. Use CDNs when possible, keep base64 placeholders lightweight, and rely on sizes to ensure responsive performance across viewports.
Check out the official NgOptimizedImage documentation for deeper use cases like server-side rendering (SSR), preload hints, and advanced loader customization.