Falytom logoFALYTOM
Games
ToolsUI ComponentsServicesProductsAbout
menu
  1. Home
  2. /Web Development
  3. /Nextjs
  4. /Image Component
Your Progress0%
0 of 70 completed

NextJS Topics

Getting Started

  • What is Next.js?
  • Next.js vs React - Key Differences
  • Creating Your First Next.js 15 Project
  • Next.js Project Structure Explained
  • App Router vs Pages Router

Routing Fundamentals

  • File-Based Routing Basics
  • Creating Pages with page.tsx
  • Dynamic Routes and Route Parameters
  • Catch-All and Optional Catch-All Routes
  • Route Groups for Organization
  • Parallel Routes
  • Intercepting Routes

Layouts and Pages

  • Understanding Layouts
  • Root Layout and Global Configuration
  • Nested Layouts
  • Templates vs Layouts
  • Loading States with loading.tsx
  • Error Handling with error.tsx

Server and Client Components

  • Understanding Server Components
  • Client Components with 'use client'
  • When to Use Server vs Client Components
  • Component Composition Patterns
  • Passing Props Between Server and Client
  • Server Component Patterns and Best Practices

Data Fetching

  • Fetching Data in Server Components
  • Parallel and Sequential Data Fetching
  • Data Fetching Patterns and Strategies
  • Caching and Revalidation
  • Revalidate and Cache Tags
  • Handling Loading and Error States in Data Fetching

Navigation and Links

  • Link Component Basics
  • useRouter Hook for Programmatic Navigation
  • usePathname and useSearchParams Hooks
  • Active Links and Navigation States
  • Redirects and Navigation Guards

Styling in Next.js

  • CSS Modules in Next.js
  • Tailwind CSS Setup and Configuration
  • Global Styles and CSS Variables
  • Next.js Font Optimization

Images and Media

  • Next.js Image Component Basics
  • Image Optimization and Best Practices
  • Working with Static Assets

Forms and Data Mutations

  • Understanding Server Actions
  • Form Handling with Server Actions
  • Form Validation and Error Handling
  • useFormStatus and useFormState Hooks
  • Revalidating Data After Mutations
  • Optimistic Updates

Metadata and SEO

  • Static Metadata Configuration
  • Dynamic Metadata Generation
  • Open Graph and Social Media Cards
  • Sitemap and Robots.txt

API Routes and Route Handlers

  • Route Handlers Introduction
  • GET and POST Request Handlers
  • Dynamic API Routes
  • Request and Response Objects
  • API Error Handling and Status Codes

Middleware and Advanced Features

  • Introduction to Middleware
  • Authentication with Middleware
  • Environment Variables and Configuration
  • Streaming and Suspense
  • Not Found and Global Error Pages

Deployment and Optimization

  • Understanding Static and Dynamic Rendering
  • generateStaticParams for Static Generation
  • Build and Production Optimization
  • Deploying to Vercel
  • Alternative Deployment Options
  • Performance Monitoring and Analytics

Real-World Projects

  • Project 1: E-commerce Product Catalog
  • Project 2: Dashboard with Authentication

Next.js Image Component Basics

Automatic image optimization with the Image component

Images are often the largest assets on web pages, causing slow loading and poor performance. The Next.js Image component solves this with automatic optimization—resizing images on-demand, converting to modern formats (WebP, AVIF), lazy loading, and preventing layout shift. You get dramatically better performance with zero configuration. Let's master optimized images in Next.js!

Why Use the Image Component?

❌ Regular <img> Tag

HTML
<img 
  src="/hero.jpg" 
  alt="Hero image"
  width="1200"
  height="600"
/>

<!-- Problems: -->
<!-- ❌ No optimization (large file sizes) -->
<!-- ❌ No format conversion (no WebP/AVIF) -->
<!-- ❌ No lazy loading (loads immediately) -->
<!-- ❌ Layout shift (image pops in) -->
<!-- ❌ No responsive sizing -->
<!-- ❌ Poor performance -->

✅ Next.js Image Component

TYPESCRIPT
import Image from 'next/image';

<Image
  src="/hero.jpg"
  alt="Hero image"
  width={1200}
  height={600}
/>

// Benefits:
// ✅ Automatic optimization
// ✅ Modern formats (WebP, AVIF)
// ✅ Lazy loading by default
// ✅ No layout shift
// ✅ Responsive sizing
// ✅ Dramatically faster

Performance Benefits

  • Smaller files: Images automatically resized and compressed
  • Modern formats: Converts to WebP/AVIF (30-80% smaller)
  • Lazy loading: Images load only when entering viewport
  • No layout shift: Reserved space prevents content jumping
  • Responsive: Serves appropriate size for each device
  • On-demand: Optimizes images when requested, not at build time

Basic Image Component Usage

Static Image (Local File)

app/page.tsx
import Image from 'next/image';

export default function Home() {
  return (
    <div>
      <Image
        src="/images/hero.jpg"
        alt="Hero image"
        width={1200}
        height={600}
      />
    </div>
  );
}

// ✅ Image in /public/images/hero.jpg
// ✅ Referenced with /images/hero.jpg
// ✅ Width and height prevent layout shift
// ✅ Automatically optimized

Required Props

TYPESCRIPT
<Image
  src="/images/product.jpg"  // Required: Image path
  alt="Product image"         // Required: Accessibility
  width={800}                 // Required*: Width in pixels
  height={600}                // Required*: Height in pixels
/>

// * width and height required UNLESS using fill prop

// ✅ src: Path to image
// ✅ alt: Description for screen readers and SEO
// ✅ width/height: Prevents layout shift, enables optimization

⚠️ Always Provide Alt Text

The alt prop is required for accessibility. Describe what's in the image for screen readers and users who can't see images. It also helps SEO!

Image Sizing Patterns

Pattern 1: Fixed Dimensions

TYPESCRIPT
import Image from 'next/image';

export function ProductCard() {
  return (
    <div>
      {/* Fixed size image */}
      <Image
        src="/images/product.jpg"
        alt="Product"
        width={400}
        height={400}
      />
    </div>
  );
}

// ✅ Use for images with known dimensions
// ✅ Width and height in pixels
// ✅ Aspect ratio maintained
// ✅ Prevents layout shift

Pattern 2: Fill Container (Responsive)

TYPESCRIPT
import Image from 'next/image';

export function Hero() {
  return (
    <div className="relative w-full h-96">
      {/* Image fills parent container */}
      <Image
        src="/images/hero.jpg"
        alt="Hero"
        fill
        className="object-cover"
      />
    </div>
  );
}

// ✅ fill prop makes image fill parent
// ✅ Parent must have position: relative
// ✅ Use object-fit for sizing behavior:
//    - object-cover: fills container, crops if needed
//    - object-contain: fits inside, maintains aspect ratio
//    - object-fill: stretches to fill

// Common use cases:
// - Hero sections
// - Background images
// - Card images
// - Responsive galleries

Pattern 3: Responsive with max-width

TYPESCRIPT
import Image from 'next/image';

export function BlogImage() {
  return (
    <div className="relative w-full max-w-3xl mx-auto">
      {/* Responsive image with max-width */}
      <Image
        src="/images/article.jpg"
        alt="Article illustration"
        width={1200}
        height={675}
        className="w-full h-auto"
      />
    </div>
  );
}

// ✅ width/height for aspect ratio
// ✅ className="w-full h-auto" makes it responsive
// ✅ Container sets max-width
// ✅ Maintains aspect ratio

Loading and Performance

Lazy Loading (Default)

TYPESCRIPT
import Image from 'next/image';

export function Gallery() {
  return (
    <div className="grid grid-cols-3 gap-4">
      {/* All images lazy load by default */}
      <Image src="/images/img1.jpg" alt="Image 1" width={400} height={300} />
      <Image src="/images/img2.jpg" alt="Image 2" width={400} height={300} />
      <Image src="/images/img3.jpg" alt="Image 3" width={400} height={300} />
    </div>
  );
}

// ✅ Lazy loading is default
// ✅ Images load when entering viewport
// ✅ Saves bandwidth
// ✅ Faster initial page load

Priority Loading (Above the Fold)

TYPESCRIPT
import Image from 'next/image';

export function Hero() {
  return (
    <div className="relative w-full h-screen">
      {/* Priority image - loads immediately */}
      <Image
        src="/images/hero.jpg"
        alt="Hero"
        fill
        priority
        className="object-cover"
      />
    </div>
  );
}

// ✅ priority prop disables lazy loading
// ✅ Image preloaded for faster LCP
// ✅ Use for above-the-fold images only
// ✅ Improves Core Web Vitals (LCP)

// When to use priority:
// ✅ Hero images
// ✅ Logo
// ✅ Above-the-fold content
// ❌ Below-the-fold images (use lazy loading)

Loading States

TYPESCRIPT
import Image from 'next/image';

export function ProductImage() {
  return (
    <Image
      src="/images/product.jpg"
      alt="Product"
      width={800}
      height={600}
      loading="lazy"    // 'lazy' (default) or 'eager'
      placeholder="blur"
      blurDataURL="data:image/jpeg;base64,/9j/4AAQSkZJRg..." // Base64 blur
    />
  );
}

// loading prop:
// - 'lazy': Lazy load (default)
// - 'eager': Load immediately

// placeholder prop:
// - 'empty': No placeholder (default)
// - 'blur': Show blur until loaded

// ✅ Blur placeholder improves perceived performance
// ✅ User sees something while image loads

Styling Images

Using className

TYPESCRIPT
import Image from 'next/image';

export function StyledImage() {
  return (
    <Image
      src="/images/avatar.jpg"
      alt="Avatar"
      width={100}
      height={100}
      className="rounded-full border-4 border-white shadow-lg"
    />
  );
}

// ✅ Use className for Tailwind or CSS
// ✅ Styles applied to <img> element
// ✅ Works with Tailwind, CSS Modules, etc.

Object Fit with Fill

TYPESCRIPT
import Image from 'next/image';

// Cover - fills container, crops if needed
export function CoverImage() {
  return (
    <div className="relative w-full h-64">
      <Image
        src="/images/hero.jpg"
        alt="Hero"
        fill
        className="object-cover"
      />
    </div>
  );
}

// Contain - fits inside, maintains aspect ratio
export function ContainImage() {
  return (
    <div className="relative w-full h-64 bg-gray-100">
      <Image
        src="/images/logo.png"
        alt="Logo"
        fill
        className="object-contain p-4"
      />
    </div>
  );
}

// object-cover: Fills, crops excess
// object-contain: Fits inside, shows all
// object-fill: Stretches to fill
// object-none: Original size
// object-scale-down: Smaller of contain or none

Rounded Images

TYPESCRIPT
import Image from 'next/image';

// Circle avatar
export function Avatar() {
  return (
    <Image
      src="/images/user.jpg"
      alt="User"
      width={80}
      height={80}
      className="rounded-full"
    />
  );
}

// Rounded corners
export function CardImage() {
  return (
    <Image
      src="/images/card.jpg"
      alt="Card"
      width={400}
      height={300}
      className="rounded-lg"
    />
  );
}

// ✅ rounded-full: Circle
// ✅ rounded-lg: Rounded corners
// ✅ Works with any CSS

Remote Images

Configure Remote Domains

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  images: {
    remotePatterns: [
      {
        protocol: 'https',
        hostname: 'example.com',
        port: '',
        pathname: '/images/**',
      },
      {
        protocol: 'https',
        hostname: 'cdn.example.com',
      },
    ],
  },
};

module.exports = nextConfig;

// ✅ Whitelist external image domains
// ✅ Security - prevents unauthorized sources
// ✅ Use remotePatterns (not deprecated domains)

Using Remote Images

app/page.tsx
import Image from 'next/image';

export default function Page() {
  return (
    <div>
      {/* Remote image from whitelisted domain */}
      <Image
        src="https://example.com/images/photo.jpg"
        alt="Remote photo"
        width={800}
        height={600}
      />

      {/* From CDN */}
      <Image
        src="https://cdn.example.com/avatar.jpg"
        alt="User avatar"
        width={100}
        height={100}
        className="rounded-full"
      />
    </div>
  );
}

// ✅ Remote images optimized like local images
// ✅ Must configure domain in next.config.js
// ✅ Works with CDNs, CMSs, etc.

Dynamic Remote Images

app/products/[id]/page.tsx
import Image from 'next/image';

interface Product {
  id: string;
  name: string;
  imageUrl: string;
}

export default async function ProductPage({
  params,
}: {
  params: { id: string };
}) {
  const product: Product = await fetch(
    `https://api.example.com/products/${params.id}`
  ).then(r => r.json());

  return (
    <div>
      <h1>{product.name}</h1>
      
      {/* Dynamic remote image */}
      <Image
        src={product.imageUrl}
        alt={product.name}
        width={800}
        height={600}
      />
    </div>
  );
}

// ✅ Image URL from API
// ✅ Optimized like any other image
// ✅ Domain must be whitelisted

Practical Examples

Example 1: Hero Section

components/Hero.tsx
import Image from 'next/image';

export function Hero() {
  return (
    <section className="relative h-screen w-full">
      {/* Background image */}
      <Image
        src="/images/hero-bg.jpg"
        alt="Hero background"
        fill
        priority
        className="object-cover"
      />

      {/* Overlay */}
      <div className="absolute inset-0 bg-black/50" />

      {/* Content */}
      <div className="relative z-10 h-full flex items-center justify-center text-white">
        <div className="text-center">
          <h1 className="text-6xl font-bold mb-4">
            Welcome to Our Platform
          </h1>
          <p className="text-xl mb-8">
            Build amazing things with Next.js
          </p>
          <button className="px-8 py-4 bg-blue-600 rounded-lg font-bold">
            Get Started
          </button>
        </div>
      </div>
    </section>
  );
}

// ✅ Full-screen background image
// ✅ priority for above-the-fold
// ✅ object-cover to fill
// ✅ Overlay for readability

Example 2: Product Grid

components/ProductGrid.tsx
import Image from 'next/image';

interface Product {
  id: string;
  name: string;
  price: number;
  image: string;
}

export function ProductGrid({ products }: { products: Product[] }) {
  return (
    <div className="grid grid-cols-1 md:grid-cols-3 lg:grid-cols-4 gap-6">
      {products.map(product => (
        <div key={product.id} className="bg-white rounded-lg shadow-lg overflow-hidden">
          {/* Product image */}
          <div className="relative w-full h-64">
            <Image
              src={product.image}
              alt={product.name}
              fill
              className="object-cover hover:scale-105 transition-transform duration-300"
            />
          </div>

          {/* Product info */}
          <div className="p-4">
            <h3 className="font-bold text-lg mb-2">{product.name}</h3>
            <p className="text-2xl font-bold text-blue-600">
              ${product.price}
            </p>
            <button className="w-full mt-4 px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
              Add to Cart
            </button>
          </div>
        </div>
      ))}
    </div>
  );
}

// ✅ Responsive grid
// ✅ fill for card images
// ✅ Lazy loading (default)
// ✅ Hover zoom effect

Example 3: Avatar Component

components/Avatar.tsx
import Image from 'next/image';

interface AvatarProps {
  src: string;
  alt: string;
  size?: 'sm' | 'md' | 'lg';
}

export function Avatar({ src, alt, size = 'md' }: AvatarProps) {
  const sizes = {
    sm: 40,
    md: 80,
    lg: 120,
  };

  const dimension = sizes[size];

  return (
    <Image
      src={src}
      alt={alt}
      width={dimension}
      height={dimension}
      className="rounded-full border-2 border-white shadow-lg"
    />
  );
}

// Usage:
// <Avatar src="/images/user.jpg" alt="John Doe" size="lg" />

// ✅ Reusable avatar component
// ✅ Multiple sizes
// ✅ Rounded styling
// ✅ Type-safe

Example 4: Image Gallery

components/Gallery.tsx
import Image from 'next/image';

interface GalleryImage {
  id: string;
  url: string;
  alt: string;
}

export function Gallery({ images }: { images: GalleryImage[] }) {
  return (
    <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
      {images.map(image => (
        <div
          key={image.id}
          className="relative aspect-square overflow-hidden rounded-lg cursor-pointer group"
        >
          <Image
            src={image.url}
            alt={image.alt}
            fill
            className="object-cover group-hover:scale-110 transition-transform duration-300"
          />
          
          {/* Hover overlay */}
          <div className="absolute inset-0 bg-black/50 opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
            <span className="text-white font-semibold">View</span>
          </div>
        </div>
      ))}
    </div>
  );
}

// ✅ Responsive masonry grid
// ✅ aspect-square for uniform sizing
// ✅ Hover effects
// ✅ Lazy loading

Image Files Structure

Organization of images in Next.js project

publicImportant
app

Select a file or folder to see details

Image Component Best Practices

1. Always Provide Width and Height

TYPESCRIPT
// ✅ GOOD: Dimensions prevent layout shift
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
/>

// ✅ GOOD: Or use fill with container
<div className="relative w-full h-96">
  <Image src="/hero.jpg" alt="Hero" fill />
</div>

// ❌ BAD: Missing dimensions causes issues
<Image src="/hero.jpg" alt="Hero" />
// Error: Missing width/height or fill prop

2. Use Priority for Above-the-Fold Images

TYPESCRIPT
// ✅ GOOD: priority for hero image
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  priority
/>

// ❌ BAD: No priority for above-fold
// Lazy loads hero image → poor LCP

// Use priority sparingly (1-2 images max)

3. Provide Descriptive Alt Text

TYPESCRIPT
// ✅ GOOD: Descriptive alt text
<Image
  src="/product.jpg"
  alt="Blue wireless headphones with noise cancellation"
  width={400}
  height={400}
/>

// ❌ BAD: Generic or missing alt
<Image src="/product.jpg" alt="product" />
<Image src="/product.jpg" alt="" />

// Good alt text:
// - Describes what's in the image
// - Helps screen reader users
// - Improves SEO

4. Use Appropriate Object Fit

TYPESCRIPT
// ✅ GOOD: object-cover for backgrounds
<div className="relative h-64">
  <Image src="/bg.jpg" alt="Background" fill className="object-cover" />
</div>

// ✅ GOOD: object-contain for logos
<div className="relative h-32">
  <Image src="/logo.png" alt="Logo" fill className="object-contain" />
</div>

// object-cover: Fills, crops
// object-contain: Fits, shows all

5. Optimize for Different Devices

TYPESCRIPT
// ✅ GOOD: Responsive with fill
<div className="relative w-full h-64 md:h-96">
  <Image src="/hero.jpg" alt="Hero" fill />
</div>

// ✅ GOOD: Responsive with className
<Image
  src="/hero.jpg"
  alt="Hero"
  width={1200}
  height={600}
  className="w-full h-auto"
/>

// Next.js automatically serves appropriate size

Key Takeaways

  • Import from 'next/image' - use Image component, not <img>
  • Automatic optimization - resizing, compression, format conversion
  • Required props - src, alt, and width/height OR fill
  • Lazy loading default - images load when entering viewport
  • priority prop - disable lazy loading for above-fold images
  • fill prop - make image fill parent container
  • Remote images - configure domains in next.config.js
  • No layout shift - dimensions prevent content jumping

What's Next?

You've mastered the Image component basics! Next, we'll explore Image Optimization and Best Practices—advanced techniques for sizing, formats, quality settings, responsive images, and performance optimization. You'll learn to squeeze every bit of performance from your images!

We'll cover image formats (WebP, AVIF), quality settings, responsive images with sizes prop, blur placeholders, and measuring image performance for Core Web Vitals.

⚡ Dramatic Performance Gains

The Image component typically reduces image sizes by 30-80% through modern formats and optimization. This dramatically improves page load times and Core Web Vitals. Always use Image instead of <img>!

Test Your Understanding

Question 1 of 4

What's the main benefit of using Next.js Image component?

Master the Next.js Image component for automatic optimization, lazy loading, and better performance!

Previous
Next.js Font Optimization
Next
Image Optimization and Best Practices

Master Next.js Images

Join 2,000+ developers building fast Next.js apps. Get the next lesson on advanced image optimization - 100% FREE.

You might also like

UI Components

Ready-made components for your projects

Developer Tools

Boost productivity with handy generators

HTML Game

Learn HTML concepts through interactive gameplay

Join Our Web Development Training Program

Master frontend & backend development with hands-on projects.

NextJS Tutorials

0 of 70 completed

Your Progress0%

Topics

Getting Started

  • What is Next.js?
  • Next.js vs React - Key Differences
  • Creating Your First Next.js 15 Project
  • Next.js Project Structure Explained
  • App Router vs Pages Router

Routing Fundamentals

  • File-Based Routing Basics
  • Creating Pages with page.tsx
  • Dynamic Routes and Route Parameters
  • Catch-All and Optional Catch-All Routes
  • Route Groups for Organization
  • Parallel Routes
  • Intercepting Routes

Layouts and Pages

  • Understanding Layouts
  • Root Layout and Global Configuration
  • Nested Layouts
  • Templates vs Layouts
  • Loading States with loading.tsx
  • Error Handling with error.tsx

Server and Client Components

  • Understanding Server Components
  • Client Components with 'use client'
  • When to Use Server vs Client Components
  • Component Composition Patterns
  • Passing Props Between Server and Client
  • Server Component Patterns and Best Practices

Data Fetching

  • Fetching Data in Server Components
  • Parallel and Sequential Data Fetching
  • Data Fetching Patterns and Strategies
  • Caching and Revalidation
  • Revalidate and Cache Tags
  • Handling Loading and Error States in Data Fetching

Navigation and Links

  • Link Component Basics
  • useRouter Hook for Programmatic Navigation
  • usePathname and useSearchParams Hooks
  • Active Links and Navigation States
  • Redirects and Navigation Guards

Styling in Next.js

  • CSS Modules in Next.js
  • Tailwind CSS Setup and Configuration
  • Global Styles and CSS Variables
  • Next.js Font Optimization

Images and Media

  • Next.js Image Component Basics
  • Image Optimization and Best Practices
  • Working with Static Assets

Forms and Data Mutations

  • Understanding Server Actions
  • Form Handling with Server Actions
  • Form Validation and Error Handling
  • useFormStatus and useFormState Hooks
  • Revalidating Data After Mutations
  • Optimistic Updates

Metadata and SEO

  • Static Metadata Configuration
  • Dynamic Metadata Generation
  • Open Graph and Social Media Cards
  • Sitemap and Robots.txt

API Routes and Route Handlers

  • Route Handlers Introduction
  • GET and POST Request Handlers
  • Dynamic API Routes
  • Request and Response Objects
  • API Error Handling and Status Codes

Middleware and Advanced Features

  • Introduction to Middleware
  • Authentication with Middleware
  • Environment Variables and Configuration
  • Streaming and Suspense
  • Not Found and Global Error Pages

Deployment and Optimization

  • Understanding Static and Dynamic Rendering
  • generateStaticParams for Static Generation
  • Build and Production Optimization
  • Deploying to Vercel
  • Alternative Deployment Options
  • Performance Monitoring and Analytics

Real-World Projects

  • Project 1: E-commerce Product Catalog
  • Project 2: Dashboard with Authentication
Falytom logoFALYTOM

Learn technologies like HTML, CSS, JavaScript, React, NodeJS and more through interactive games, tutorials, components and free tools. Transform your businesses with AI chatbots, SEO-optimized websites, and professional development services.

© 2025 Tomilola Group
  • Facebook logo
  • Twitter logo
  • Instagram logo
  • LinkedIn logo
  • GitHub logo
  • YouTube logo