Type to generate UI components from text

OR

Browse thousands of MUI, Tailwind, React components that are fully customizable and responsive.

Explore Components

How to Use NextJS Image Component to Optimize Images

Images are a critical component of web design and development, as they significantly enhance user experience and provide insight into products and brands.

Unique product, facility, and screenshot images elicit greater emotional engagement than generic assets or text content. Images add value to blog posts, landing pages, and other digital content.

From a software perspective, images like product catalogs, storefront galleries, screenshot tutorials, and marketing banners have become integral components of modern web and mobile applications.

Dynamic image loading, transformation, optimization, and delivery are now common requirements for performant and responsive applications. Platforms like Next.js provide declarative frameworks to streamline working with images in code.

Problems Introduced by Wrong Usage of Images

However, adding images to a website can present several problems, including slow loading times, large file sizes, and compatibility issues with different devices and browsers which in turn can affect website performance thereby degrading the user experience and leading to increased bounce rate.

To avoid these issues, it is recommended to optimize images by compressing them without sacrificing quality, using appropriate file formats, and resizing them to fit the website’s layout. Enter Next/image. The Next/image helps address these challenges associated with delivering performant images on the web and more. The Next/image was introduced in NextJS v10.

NextJS Image Component

Purecode AI is a repository for your top MUI, Tailwind, React Components, and Templates. Browse thousands of MUI, Tailwind, and React components that are fully customizable and responsive.

Importance of Images in Web Design

There are numerous advantages to having images on your website, blog posts, or your articles. In this section, I will briefly outline some of the reasons why you need to include images on your website:

  1. Original, high-quality images are crucial for effective web design and SEO. Unlike stock photos, original images can create an emotional connection and give insight into a company.

  2. Product shots, facility photos, and screenshots engage users better than text alone. Images boost rankings in standard and visual searches.

  3. Statistics show internet users browse pictures before the text, it has been proven according to a study that the human brain processes images 60,000 times faster than text. Optimized images spread virally, improve user experience and reduce bounce rates.

  4. Image SEO has many benefits. It increases image search rankings since users often start there. Optimized visuals are more likely to be shared. Compelling pictures enhances user experience over text. With expanding visual search capabilities, image SEO is vital for retailers. Optical elements like infographics attract users. Websites must optimize images as a powerful SEO asset.

In this article, you will learn about the NextJS <Image /> component, how to use it to deliver performant images on the web,

Overview of NextJS

Next.js is an open-source front-end web development framework built on top of React, a JavaScript library for building user interfaces. It provides an application development environment for building server-side rendered (SSR) and statically generated (pre-rendering) React applications using Node.js. Many developers have built boilerplates, themes, and open-source web applications around NextJS. We wrote a comparison article detailing why and when you should choose what framework between NextJS and Gatsby.

NextJS Logo

Some key features and capabilities of Next.js include:

  • File-system Based Routing – Routes are defined in the pages folder rather than explicit route configuration. This allows automatic code splitting and server-side rendering.

  • Server-side Rendering (SSR) – It renders pages on the server rather than the client for faster page loads and better SEO.

  • Static Site Generation (SSG) – Pages can be pre-built at build time as static HTML files. This allows fast page loads without server computation.

  • Image Optimization – Automatic image optimization with support for image lazy loading and resizing.

  • API Routes – API endpoints can be created to build REST APIs serving data.

  • Fast Refresh – Retain application state while editing React components for faster development.

  • Built-in CSS Support – Built-in support for CSS and Sass without extra configuration.

  • TypeScript Support – First-class support for TypeScript for static typing.

Prerequisites

For you to follow along with this article, you should have an understanding of:

You do not have to start from scratch when developing your web applications. Purecode AI has simplified the process of building web applications by providing you with plug-and-play ready-to-use codes for your components. Check out our repository of 10,000+ AI-generated custom components.

Purecode AI landing page

Preparing Image Assets for Optimization

Before utilizing the Image component, it is important to prepare image assets to achieve optimal performance. Consider a Content Delivery Network (CDN) like Cloudinary to host assets for large volumes of dynamic images. CDNs provide caching, compression, and on-demand resizing.

Here are key considerations for serving performant images:

  1. Select Appropriate Image Format: Of JPEG, PNG, and WebP, WebP is recommended due to superior lossy/lossless compression without quality loss. WebP provides faster load times and broad browser support. Tools like WebP Converter facilitate conversion.

  2. Generate Responsive Image Sizes: Serving properly sized images for each device is critical for optimization. Sending large 1080×800 images to small 100×100 screens wastes bandwidth, impacting page load speed and metrics. Use tools like Cloudinary’s Responsive Breakpoint Generator to produce sizes for different viewports.

  3. Compress Image Assets: Keep images below 1 Mb in size. Large files should be reduced to a reasonable threshold without sacrificing quality. Leverage tools like TinyPNG and Compressor.io for compression.

After manual optimization, the NextJS Image component can further enhance performance.

Understanding the Nextjs Image Component

The Next.js Image component simplifies the serving and optimization of images in your NextJS web applications. It’s similar to the native HTML <img/> element but has a few differences. In this section, we will take a look at the differences between the HTML tag and the next/image.

What the Next.js Image Component Does

The function of the Next.js Image component revolves around enhancing the performance and user experience related to images on your NextJS web app. It acts as a wrapper around the native HTML img element, offering a range of features that contribute to improved loading times, responsive design, and overall optimization.

These features include image optimization, performance improvement, automatic compression of images, lazy loading of images, and more.

How the Next.js Image Component Works

The Next.js Image component operates by rendering images to the browser based on specified attributes, akin to the functionality of the native img HTML element. However, it goes beyond the basics, offering a dynamic selection of the optimal image size based on the current browser viewport width.

Check out this YouTube video tutorial below to get a good grasp of the Next/image:

Defining Image Asset Origins and Pricing

Some image optimization platforms like Vercel and Imgix base pricing on the quantity of original image assets served. Both offer a free tier allowing up to 1,000 origin images per month.

The term “origin” refers to the source location of image assets. Options include databases, build artifacts, or preferable object storage like S3 buckets.

When specifying the src property in Next.js Image, you define the origin location of that image asset. For example, if images are stored in S3:

  • 2,000 total image assets in S3 storage

  • 800 images accessed during the billing cycle

  • You would be billed for 800 origin images based on usage

Other platforms may price on total image transformations or bandwidth usage.

The modern approach is to store a single high-resolution version in S3 and generate variations on the fly via services like Vercel, Imgix, Cloudinary, or ImageKit. This reduces maintenance despite higher costs.

When to Use Custom Image Loaders

Image optimization platforms typically provide:

  • Resizing original assets

  • Compression

  • Format optimization

  • CDN delivery

  • Image transformations

Vercel handles the first 4 responsibilities. Reasons to use a custom loader with Vercel include:

  • Requiring transformations

  • Different pricing model

  • Existing platform lock-in like Cloudinary

Incorrect Custom Loader Usage

When using Cloudinary and Next.js without a custom loader, avoid directly passing transformed URLs to the Image component src. This results in redundant optimizations and suboptimal quality.

Instead, use the unoptimized prop or configure a Cloudinary loader in next.config.js.

Correct Custom Loader Usage

To leverage Cloudinary, define its loader in next.config.js. Then pass relative paths to Next.js Image and transformations will occur automatically via the loader integration.

Extend the built-in loader if needing additional transformations in src.

Using CloudFront CDN

CloudFront solely accelerates delivery, unlike optimization services. You can either:

  1. Use Vercel’s API for optimizations

  2. Create Lambda functions for image processing

It is redundant to use CloudFront as a loader. Instead, treat it as the origin Vercel downloads from for further optimization.

What is the “Loader” in Next/image

A critical aspect of the Next.js Image component is the concept of the “loader“. The loader is a prop used to determine how images are retrieved, especially those generated in the srcset attribute by the Image component.

The loader should not be confused with regular CSS loaders or skeletons displayed when items or images are still loading from a network request.

This loader prop plays a pivotal role in shaping the behavior of the component and dictates where and how the images are sourced. In essence, the loader is responsible for fetching the images specified by the Image component. For example, if the source is a partial URL such as profile.png, we can write a loader to resolve the full URL, say https://example.com/profile.png.

By default, the Next.js Image component utilizes the “default loader,” which seamlessly integrates with Vercel’s Image Optimization API. This default configuration streamlines common operations such as image compression, resizing, lazy loading, and CDN delivery. However, developers have the flexibility to customize the loader, enabling them to integrate other image optimization services or implement bespoke solutions tailored to their specific needs.

Benefits of next/image

There are different advantages and benefits of working with the NextJS image for improving website performance and user experience.

  • The NextJS Image component automatically optimizes images by compressing file sizes and serving modern formats supported by the browser. This saves bandwidth and ensures fast loading.

  • Next/image also enables lazy loading so images load as they enter the viewport rather than all at once.

  • In addition to performance, next/image enhances the user experience. This is because optimized images lead to faster page loads and less layout shifting. By handling width and height, it minimizes Cumulative Layout Shift for a smoother viewing experience.

  • The NextJS image component also supports priority loading so important images are loaded first.

Using the NextJS Image Component

To get started, you will need to import the <Image /> component from the next/image like so:

import Image from "next/image";

Then use the component as shown below:

import Image from "next/image";
import profilePic from "../public/profile.webp";

const Profile = () => {
  return (
    <>
      <h1> User Profile </h1>
      <Image
        src={profilePic}
        alt="Picture of the author"
        width={500}
        height={500}
      />
    </>
  );
};

The example above shows a basic usage of the NextJS Image component. The src, the width, the height, and the alt props are required and must be supplied to use the Image component.

In the code snippet above, the user profile picture will be rendered by the NextJS Image component.

Next/Image Properties

The image component has sixteen properties as of this writing. Here is a quick rundown of each property.

Props Required

  • src: This property is used to specify the image’s source. The source can be an external URL or a file that has been statically imported. The type of its prop is a string.

  • width and height: They define an image’s dimensions. The type of prop they have is a number. An example can be 500 just like in the code snippet above. The width and height do not determine the rendered size of the image file.

  • alt: Provides alternative text for an image. When the image fails to load, this text is displayed. The alt text is also important for SEO and accessibility. The type of its prop is a string.

Optional Props

  • loader: A custom function that generates an image source’s complete URL. If the source is a partial URL, such as profile.png, we can write a loader to resolve the full URL, such as https://example.com/profile.png.

  • fill: We can use the fill prop instead of setting the width and height of an image. It causes the image to occupy all available space in its parent element. Its prop type is boolean, and its position is set to “absolute” by default.

  • sizes: Used to define responsive image sizes at various breakpoints. The image component will generate the appropriate srcSet versions of the images based on the sizes specified. Only images with the fill layout require this property. It has the string prop type and the default value of 100vw (full-screen width).

  • quality: A number between 1 and 100 that determines the image’s quality after optimization. Its prop type is number, and the default value is 75.

  • priority: By default, NextJS lazy loads all images. When the priority of an image is set to true, the next/image preloads that image. Its prop type is boolean, and it is set to false by default.

Advanced Props

  • style: Allows us to directly pass an object of CSS styles to an image component. This gives us more control over image styling.

  • onLoadingComplete: A callback function that is executed once the image has completed loading and the placeholder has been removed.

  • onLoad: A callback function that is executed once the image has completed loading.

  • onError: A callback function that is invoked if the image fails to load.

  • loading: Defines an image’s loading strategy. By default, it is set to lazy. It can also be set to eager, which means that the image will be loaded immediately.

  • blurDataURL: Used in conjunction with the placeholder prop. It specifies a data URL for a blurred version of the image that serves as the placeholder. The blurDataURL is a base64-encoded image DATA URL to be used as a placeholder image before the src image fully loads. It will be enlarged and blurred, so a very small image of 10px or less is recommended. Only takes effect when combined with placeholder=”blur” .

This code snippet below demonstrates the usage of the NextJS Image component with all props used:

import Image from "next/image";

export default function IndexPage() {

  const loaderFunction = ({ src, width, quality }) => {
    return `https://res.cloudinary.com/${src}?w=${width}&q=${quality || 75}`
  };

  const styles = {
    borderRadius: '50%',
    border: '1px solid #9966ff',
  };

  return (
    <div>
      <h1> User Profile </h1>
      <Image
        loader={loaderFunction}
        src="/profilePic.png"
        width={500}
        height={500}
        alt="Picture of the author"
        quality={95}
        fill={true}
        loading="lazy"
        priority={true}
        style={styles}
        blurDataURL="data:image/jpeg..."
        placeholder="blur"
        onLoad={(event) => console.log("Loading complete" + event)}
        onError={(event) => console.log("Failed to load" + event)}
        sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
        onLoadingComplete={(img) => console.log("image loaded successfully" + img)}
      />
    </div>
  );
}

Next/Image Properties with complete properties

Best Practices when Using the Next.js Image Component:

When using the next/image, ensure to consider the following points so as to maximize the benefits from Next image optimization:

  • Import the Image Component – Import the Image component from ‘next/image’ to utilize it in your app.

  • Optimize Image Formats – Use modern formats like WebP and AVIF that are optimized for the web.

  • Specify Width and Height – Set static width and height props so the space is reserved before loading.

  • Lazy Load Images – Images load lazily as user scrolls instead of all images loading at once.

  • Use Image Loader – Leverage the default loader or configure a custom one for resizing and optimization.

  • Set Proper Src – Point to optimized image file or use relative url paths with configured loader.

  • Consider Aspect Ratio – Use property to maintain ratio if width/height change or use fill layout.

  • Handle Remote Images – For external images, you may need to detect dimensions via API first.

  • Use Image CDN – Configure images to be served from a high-performance content delivery network.

  • Optimize Original Assets – Compress and use appropriate resolutions on original image assets.

  • Measure Performance – Monitor core web vitals like LCP related to images loading correctly.

  • Add Image Placeholders – Display placeholders while image is loading to prevent layout shift.

  • Size Images Responsively – Use srcset widths to serve smaller sizes to smaller screens.

  • Protect Against Attacks – Validate src and configure domains to prevent malicious images.

Comparison of Image Optimization Strategies with and without Next.js Image Component

The table below shows a comparison of image optimization techniques with and without the Next.js Image component:

FeatureWithout Next.js ImageWith Next.js Image
ResponsivenessManual media queries and srcset requiredAuto-generated srcset
Lazy loadingMust add library or custom logicBuilt-in lazy loading
CompressionManual optimization before uploadAuto compression and webp conversion
CDN cachingRequires separate CDN setupLeverages Vercel Edge Network
Image sizingMultiple resized copies storedSingle original, resized on demand
CachingManual cache headersAutomatic browser and CDN caching
Page speedMultiple unoptimized imagesFast with lazy loading and CDN
Core web vitalsLikely poor LCP and CLSOptimized for LCP and CLS
Ease of useComplex image handling logicSimple Image component
CostStorage for all resized copiesUsage-based image optimization

What You Have Learned

This article lets you understand how the Next.js Image component works to optimize images on your NextJS web application. The Image component handles rendering responsive images by generating a srcset with different sizes.

It lazy loads images only when they enter the viewport. Under the hood, the default loader taps into Vercel’s Image Optimization API to handle resizing, compression, and conversion to efficient image formats like WebP.

You learned how loaders work in Next.js Image. The default loader uses Vercel’s API, but you can configure a custom loader to leverage an external service like Cloudinary just like we did in our example. Custom loaders are useful for image transformations or reducing costs. You also now know the difference between an image loader and an image origin.

The article covered strategies for dealing with remote images where dimensions are unknown. You can standardize sizes, use fill layouts, probe the images, or fall to a native img tag.

If you want to learn more on next/image, check out this YouTube video tutorial below:

If you want to speed up development time and not have to worry about writing custom codes yourself, check out our repository of more than 10,000+ AI-generated custom components for you to choose from.

Further Readings

If you enjoyed reading this piece, be sure to check out the following documentation and articles from our blog:

Emmanuel Uchenna

Emmanuel Uchenna

Emmanuel is an experienced and enthusiastic software developer and technical writer with 4+ proven years of professional experience. He focuses on full-stack web development. He is fluent in React, TypeScript, VueJS, and NodeJS and familiar with industry-standard technologies such as version control, headless CMS, and JAMstack. He is passionate about knowledge sharing.