Next.js' Image component is well documented, and also confusing, but why?
One of the main reasons is because, under the hood, the
<Image/> component uses native HTML responsive images, which are confusing.
So when you take something that already confuses people, and then add a swathe of features on top to cover all the potential use-cases, you need a lot of documentation to help all the confused developers.
This post explains some nuances that may have left you feeling confused, without knowing why, or wanting to invest the time into finding out why things are the way they are.
Here's an example of a native HTML image.
You need to at-least have a
src attribute with a value,
and for accessibility purposes,
a description of the image in the
You can then enhance the experience by adding various sizes of the same image at different resolutions, this is called resolution switching.
If you add a width and height, and apply a dash of CSS to your images, they will also respect the aspect ratio of the image. The example below has an aspect ratio of 2/1.
Finally, you can add the
Providing you supply these attributes, the web browser takes the values and decides which image to serve based on the following criteria:
- viewport width
- width of media described by the descriptors, e.g.
- device pixel density
In the case of the previous example, if the viewport width is less than
768px, any of the images could be served.
1, and the viewport width is
400px or less,
goat-400.jpg is served, however, if
goat-600.jpg is served instead as it has more pixels.
Above a viewport width of
768px I specified,
sizes, that the physical size of the image is
that tells the browser to only get smaller images.
This complexity is what
next/image is built on top of.
Next Image component
<Image/> component uses some of the same props as
<img/>, here are the ones you'll mostly use:
Notice the missing
One of the convenient features of
<Image/> is that
srcset is taken care of for you,
automatically, based on what you provide via
By default, if you supply a
height, this is the kind of
srcset that is output.
Due to the
the browser's decision about which images
to serve at different
devicePixelRatio is already made,
I'm not a fan of using
to contain a granular list of images at various sizes
appended by width descriptors e.g.
I then use
to inform the browser how big my images are at any given point,
the information allows the browser to pick the most optimal image.
The default behaviour with
next/image doesn't work like this,
and can only be enabled by using the
but produces some odd results.
My preference in the following example is to use
enter a value of
"280px, (min-width: 768px) 420px",
and get a srcset like this:
However, I get this:
I can't do anything to stop that from happening,
other than not using
You might have never come across this, it seems like a hidden feature.
I stumbled upon it when I decided to use
I didn't expect the vast array of images I got in the previous example.
The defaults cover a lot of bases, but I think this is an area for improvement. Imagine the HTML bloat on a busy product catalogue page, it's excessive, and completely unexpected.
The reason for the vast array of sizes is down the default configs
that come from
They can be overridden in
next.config.js, but its a blanket rule,
I'd prefer to pass in a sizes value on a case-by-case basis,
and it be used as the value, overriding the default config.
How they must have intended this
Next.js provide documentation on how to use
but it's an "either, or" solution,
and doesn't fit with how native responsive images work.
It's like they're recommending the default behaviour for the majority of cases,
sizes is for other cases,
but due to the way it works it's sub-optimal.
We shouldn't have to add a random value like
50vw to get a smaller
that's just completely wrong.
This is from the docs:
The behaviour is unpredictable, and seems unintended, and there are a number of GitHub issues on the topic.
I'd prefer a single way to generate
It would be more flexible, less confusing, and less of a surprise feature.
I'd also like it if,
when I use the
sizes attribute I get an array of images
that relate to the values used in
and up-scaled versions of the same images at different resolutions.
sizes should be a front and centre feature,
not something that feels like it's hidden away because it might confuse people,
the end result is even more complicated.
Written by Morgan Feeney
I’ve been designing and developing for almost 2 decades.
Read about me, and my work.
For juicy tips and exclusive content, subscribe to my FREE newsletter.