NgOptimizedImage (v15)
📚 What is NgOptimizedImage?
NgOptimizedImage is a directive for optimized image loading:
- Lazy loading: Images load only when visible (loading="lazy")
- Priority loading: LCP images loaded immediately (priority)
- Automatic srcset: Responsive images for different screens
- CDN integration: Works with image CDNs (Cloudinary, ImageKit, etc.)
- Size enforcement: Prevents layout shifts with width/height
- Warnings: Development warnings for best practices
🎯 Interview Questions
- Q1: What are the benefits of NgOptimizedImage?
- A: Lazy loading, priority hints for LCP, automatic srcset generation, size enforcement to prevent CLS, CDN integration.
- Q2: When should you use the priority attribute?
- A: For above-the-fold images that are Largest Contentful Paint (LCP) candidates. Disables lazy loading.
- Q3: Why is width and height required?
- A: To reserve space and prevent Cumulative Layout Shift (CLS). Required for non-fill mode images.
- Q4: What is fill mode?
- A: Image fills parent container, no width/height needed. Parent must have position: relative.
🔧 Live Demo - Optimized Images
Standard with width/height
Width and height prevent layout shift
Priority Image (LCP)
Priority: loads immediately, no lazy loading
Fill Mode (responsive)
Fill: image fills parent, parent needs position:relative
With Placeholder
Placeholder: blur effect while loading
📋 Best Practices
- ✓Use
priorityfor above-the-fold LCP images - ✓Always provide width and height (or use fill)
- ✓Use
fillfor responsive images in containers - ✓Configure image loaders for CDN optimization
- ✗Don't use for base64 inline images
- ✗Don't use priority on lazy-loaded below-the-fold images
💻 NgOptimizedImage Code
import { NgOptimizedImage } from '@angular/common';
@Component({
imports: [NgOptimizedImage],
template: `
<!-- Standard image with width/height -->
<img
ngSrc="image.jpg"
width="400"
height="300"
alt="Description"
/>
<!-- Priority image (LCP) - loads immediately -->
<img
ngSrc="hero.jpg"
width="800"
height="400"
priority
alt="Hero image"
/>
<!-- Fill mode - responsive -->
<div style="position: relative; width: 100%; height: 300px;">
<img
ngSrc="cover.jpg"
fill
style="object-fit: cover"
alt="Cover image"
/>
</div>
<!-- With placeholder blur -->
<img
ngSrc="photo.jpg"
width="400"
height="300"
placeholder
alt="Photo"
/>
<!-- With srcset sizes hint -->
<img
ngSrc="responsive.jpg"
width="800"
height="600"
sizes="(max-width: 768px) 100vw, 50vw"
alt="Responsive image"
/>
`
})
export class ImageComponent {}
// ===== Image Loader Configuration =====
// In app.config.ts
import { provideImageKitLoader } from '@angular/common';
// Or: provideCloudinaryLoader, provideCloudflareLoader, etc.
export const appConfig = {
providers: [
provideImageKitLoader('https://ik.imagekit.io/your-id'),
]
};
// Custom loader
import { IMAGE_LOADER, ImageLoaderConfig } from '@angular/common';
const customLoader = (config: ImageLoaderConfig) => {
return `https://cdn.example.com/${config.src}?w=${config.width}`;
};
export const appConfig = {
providers: [
{ provide: IMAGE_LOADER, useValue: customLoader }
]
};