How to use Image component in Next.js with unknown width and height

February 24, 2022
How to use Image component in Next.js with unknown width and height

Next.js Image component from next/image is a powerful extension of the HTML <img> tag, including a number of advantages such as:

  1. Improved Performance: Always serve correctly sized image for each device, using modern image formats
  2. Visual Stability: Prevent Cumulative Layout Shift automatically
  3. Faster Page Loads:  Images are only loaded when they enter the viewport, with optional blur-up placeholders
  4. Asset Flexibility: On-demand image resizing, even for images stored on remote servers

The Problem arises from the requirement of a fixed size...

Because Next.js doesn’t have access to remote files at build time it is required to add the width and height prop manually or to specify a layout prop. Adding objectFit cover will also fix the distortions by truncating the image.

<Image
src={url}
width={200}
height={400}
//objectFit="cover"
//layout="fill"
/>

What if we want to keep the original sizes for the remote images?

Next.js Image component already calculates the sizes for the static import images. For remote images we need to use another library... probe-image-size.

This package enables us to probe the image's sizes without actually downloading the entire image. To do this we need to pass the URL of the image.

const size = await probe(url)
...
<Image
src={url}
width={size.width}
height={size.height}
/>

Usage with SSG

Static Site Generation enables us to get the image sizes at build times, creating a faster user experience. We use getStaticProps to probe the sizes. After all the Promises have finished, we return the images as props.

/pages/index.tsx

import Image from "next/image";
import probe from "probe-image-size";
export const getStaticProps = async () => {
const images = [
{ url: "https://i.imgur.com/uCxsmmg.png" },
{ url: "https://i.imgur.com/r4IgKkX.jpeg" },
{ url: "https://i.imgur.com/dAyge0Y.jpeg" }
];
const imagesWithSizes = await Promise.all(
images.map(async (image) => {
const imageWithSize = image;
imageWithSize.size = await probe(image.url);
return imageWithSize;
})
);
return {
props: {
images: imagesWithSizes
}
};
};
//...
export default function IndexPage({ images }) {
return (
<>
{images?.map((image) => (
<Image
key={image.url}
src={image.url}
width={image.size.width}
height={image.size.height}
/>
))}
</>
);
}

Domains

To enable remote images and protect your application from malicious users, you must define a list of remote domains that you intend to access this way. This is configured in your next.config.js file, as shown below:

next.config.js

module.exports = {
images: {
domains: ["i.imgur.com"]
}
};

Reactions

Share Post

Logo

© Andrew Dorobantu - 2022