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

Demo image

Width and height prevent layout shift

Priority Image (LCP)

Priority demo image

Priority: loads immediately, no lazy loading

Fill Mode (responsive)

Fill mode demo

Fill: image fills parent, parent needs position:relative

With Placeholder

Placeholder demo

Placeholder: blur effect while loading

📋 Best Practices

  • Use priority for above-the-fold LCP images
  • Always provide width and height (or use fill)
  • Use fill for 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 }
  ]
};