Product Images That Don't Byte with the Next.js Image Component

author
Colby Fayock

Images and media are what make the web special. Being able to visit your favorite online shop and see what a product actually looks like before buying it can give you confidence when spending your hard-earned money.

But when those images take forever to load, you get frustrated. And when people visit your online store and experience a page that takes a long time to load, they get just as frustrated as you do.

Why does performance matter with ecommerce?

Performance matters no matter the type of project. Providing a good user experience should be fundamental to anything we build. But it becomes even more critical to a business when dealing with an online store.

Every byte you serve can have an impact as to whether the person on the other end of the browser will wait for that page to load or if they'll stop wasting their time and move on to something else.

As shown by eBay and countless other studies, page speed matters! eBay particularly saw that by improving the load time of their site by 100ms, they increased the amount of times people added a product to their cart by 0.5%.

eBay saw 0.5% increase in “Add to Cart” with 100ms improvement in load time

While 0.5% doesn’t really seem like a lot, consider the scale of eBay. In 2020, eBay saw $30.74 billion in sales. 0.5% of that is $153.7 million. That's still a lot of money!

Consider that’s also only a 100ms improvement. For some projects, there could be easy wins that could shave off over a full second from the load time. For smaller shops, that can make a big difference!

The bottom line is performance directly correlates to conversion. Paying attention to how long it takes to load your site is more than just a better user experience, it’s helping to bring more sales.

How can the Next.js Image Component help?

Among a variety of other components Next.js provides out-of-the-box, the Image Component is an extension of the HTML img element that wraps additional capabilities like image optimization, automatically serving images in modern formats, and responsiveness.

While you’ll often see site generators build these images at compile time, Next.js instead serves these images as the page requests them, being able to provide intelligent loading for those assets.

Because Next.js dynamically serves these images for each request, the default configuration won’t let you statically generate the images for your site with next export.

By using the Next.js Image Component, you can add the images to your project just like you would the standard img tag and be confident that you’ll be serving optimized images to your website visitors.

How to use the Next.js Image Component

To show how this works, I bootstrapped a new app with Create Next App.

I like space, so I added a picture of a galaxy to my app using a picture from nasa.gov.

<div>
<img src="/galaxy.jpg" width={4060} height={2117} />
</div>

Adding an image to a Next.js app

That image looks pretty cool, but that image’s size is 2.9mb! That’s huge! But that’s kind of expected given it’s the raw image at a resolution of 4060x2117.

Now moving that to a Next.js Image, I don’t really have to do much.

At the top of the page, we can import the Image component:

import Image from 'next/image'

Then we can update our img tag to the Next.js Image Component.

Using the Image Component is much like using the standard HTML img tag. There are a few required attributes:

  • src: path to your image
  • width: width in pixels as a number (no units)
  • height: height in pixels as a number (no units)

You can also use external links as the source of your image, but you need to configure it in your next.config.js.

We already have all of those values set, so with our image, we can change it from the img tag to the Image Component:

<div>
<Image src="/galaxy.jpg" width={4060} height={2117} />
</div>

Now when trying to load the image in the browser, the image dropped down from 2.9mb to 799kb!

Using the Image Component in a Next.js app

If you look closely, you can also see that the image is now being served as WEBP instead of a JPG, a modern image format for the web.

While this is a bit extreme of an example (typically we should be more conscious about the size of the images we load), this could realistically happen in scenarios where you’re not the one managing the images getting added or someone simply forgot to check how big that image was before dropping it in.

Without much work, we’re providing an optimized image that was converted from JPG to WEBP. Pages now require less content for visitors to download which result in faster page load speeds.

Making our Next.js images responsive

The Image Component comes with a few other props and options out of the box, one being the layout prop.

By setting the layout, we can tell Next.js how to display the image, whether it’s:

  • fixed: won't resize
  • intrinsic: will shrink, but won't grow past original dimensions
  • responsive: will scale the image up and down, including the size
  • fill: will fill the image to the size of the parent element

The interesting option to us here is to set layout to responsive. Not only will our image resize as the viewport changes, Next.js will provide a srcset attribute which will load different images at different sizes depending on how big the viewport is.

To try this out, we can add the prop to our Image Component:

<div>
<Image src="/galaxy.jpg" width={4060} height={2117} layout="responsive" />
</div>

If you’re following along with the Create Next App, if you try to reload at this point, you’ll actually see our image disappears.

Hidden image using responsive Image layout in Next.js

The issue, is when Next.js tries to make the Image responsive, it bases that responsiveness based off of the parent. Because by default in our app, our containing div doesn’t have a width set, whether a fluid width or fixed, our responsive image can’t find space to fill.

For our example, we can fix this by setting a width of 100% on our div:

<div style={{width: '100%'}}>
<Image src="/galaxy.jpg" width={4060} height={2117} layout="responsive" />
</div>

And now if we reload the page, we can see our image again.

Responsive Image in Next.js

The cool part though, looking at the source, Next.js is now dynamically setting the srcset attribute along with a few different versions of our image.

Next.js responsive Image with srcset

That means, the browser will be able to dynamically load different image sizes depending on the size of the browser. If our visitor is on a smaller device, they won’t have to load the same large images as visitors on a desktop!

Driving more sales with a better UX

Images are just one part of how we can focus on providing a better user experience to our visitors. Not paying attention to your images could lead to serving your customers huge images, costing them bandwidth and time. This leads to costing you and your business sales.

Fortunately, Next.js makes this easy with the Image component, allowing us to spend more building beautiful experiences while the framework robots do the hard work.