The Problem with Standard <img> Tags

Traditionally, using an <img src="..."> tag on the web is inefficient. You often serve a huge, high-resolution image to all devices, from a 4K desktop monitor to a small mobile phone. This leads to:

  • Slow Page Loads: Large image files are often the biggest cause of slow websites.
  • Wasted Bandwidth: Mobile users on slow connections download unnecessarily large files.
  • Layout Shift (CLS): Images loading in can cause the page content to jump around, creating a poor user experience.

The Solution: The next/image Component

Next.js provides a built-in <Image> component that solves all these problems automatically. It's a modern, drop-in replacement for the <img> tag.

Key Features & Benefits:

  • Automatic Resizing: It generates multiple smaller versions of your image and serves the most appropriate size based on the user's device viewport.
  • Modern Formats: It automatically converts images to modern, highly efficient formats like WebP or AVIF if the user's browser supports them.
  • Lazy Loading: Images outside the initial viewport are not loaded until the user scrolls near them, saving initial load time and bandwidth.
  • Prevents Cumulative Layout Shift (CLS): It requires width and height props to reserve space for the image before it loads, preventing content from jumping.

How to Use the <Image> Component

1. For Local Images

Place your images inside the public directory. Then, you can import them and use them in the component.

public/profile-picture.jpg (This is your source image file)

src/app/page.js

JavaScript


import Image from 'next/image';
// You can also just use a string path starting with /
import profilePic from '/public/profile-picture.jpg';

export default function HomePage() {
  return (
    <div>
      <h1>Welcome to my page!</h1>
      <Image
        src={profilePic}
        alt="A picture of the author"
        width={500} // The intrinsic width of the image file in pixels
        height={500} // The intrinsic height of the image file in pixels
        // You can still use CSS to make it responsive! The props are for aspect ratio.
      />
    </div>
  );
}

2. For Remote Images

You can also use images hosted on other domains. For security, you must tell Next.js which domains you trust to serve images from.

next.config.js

JavaScript


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

module.exports = nextConfig;

Now you can use URLs from that domain in your <Image> component.

JavaScript


import Image from 'next/image';

export default function RemoteImage() {
  return (
    <Image
      src="https://images.unsplash.com/photo-1682687220247-9f786e34d472"
      alt="A picture of a desert landscape"
      width={1200}
      height={800}
    />
  );
}

Handling Other Static Assets

For other static files like favicons, robots.txt, or fonts that you don't want to be processed by the build pipeline, you should place them in the public directory.

  • A file at public/favicon.ico can be accessed at /favicon.ico.
  • A file at public/my-file.txt can be accessed at /my-file.txt.

This directory is the perfect place for any static assets that need to be served from the root of your domain.