next.js icon indicating copy to clipboard operation
next.js copied to clipboard

Image component does not generate accurate srcsets

Open OskarGroth opened this issue 2 years ago • 2 comments

Verify canary release

  • [X] I verified that the issue exists in Next.js canary release

Provide environment information

Let's say I want to display an image on my website. The image is to be displayed as 24px, but I want to provide a 48px version via a @2x srcset for Retina users.

I add a 48x48px png of the image to my files. Then I create an image like:

<Image src={author.avatar} width={24} height={24} layout="raw" />

The HTML produced by NextJS becomes the following:

<img src="/_next/image?url=%2Fimages%2Favatar-small.jpg&amp;w=400&amp;q=75"
height="24" width="24" decoding="async" data-nimg="raw"
style="aspect-ratio:24 / 24"
srcset="/_next/image?url=%2Fimages%2Favatar-small.jpg&amp;w=400&amp;q=75 1x">

As you can see, the image is fetched with the argument w=400 and only in 1x size. Inspecting the resource, I can see that NextJS is generating the asset in a size as close to 400px as possible, which in this case becomes 96px (asset size * 2).

Screenshot 2022-05-28 at 16 33 33

According to the documentation, the only way to accurately represent the image the way I want (accurate srcset dimensions) is to add the image size to my imageSizes in my next.config.js. Indeed, if I add imageSizes: [24, 48] to my config and restart my server, the HTML output now becomes:

<img src="/_next/image?url=%2Fimages%avatar-small.jpg&amp;w=48&amp;q=75"
height="24" width="24" decoding="async" data-nimg="raw"
style="aspect-ratio:24 / 24"
srcset="/_next/image?url=%2Fimages%2avatar-small.jpg&amp;w=24&amp;q=75 1x,
/_next/image?url=%2Fimages%2Fcindori-avatar-small.jpg&amp;w=48&amp;q=75 2x">
Screenshot 2022-05-28 at 16 43 56

Which is exactly what I want, a 1x srcset at w=24px and a 2x srcset at w=48px. No fidelity loss and no data wasted.

The problem is that I must do this for every single image in my whole website for this to work. Adding 1x and 2x image widths to the imageSize array in the config is not only extremely cumbersome, it is actually not even a viable solution because NextJS caps the array to 25 entries.

Why is the Image component, with all its bells and whistles, not built to handle such a basic requirement? Am I missing something fundamental here? Is there any efforts being made to adress this massive shortcoming?

What browser are you using? (if relevant)

Safari 15.4

How are you deploying your application? (if relevant)

Vercel

Describe the Bug

The NextJS Image component is unable to generate accurate 1x and 2x image srcsets for custom image sizes.

Expected Behavior

The NextJS Image component should be able to generate accurate 1x and 2x image sizes without any custom configuration.

To Reproduce

See description.

OskarGroth avatar May 28 '22 14:05 OskarGroth

Stumbled across this while fighting the same battle. This is such an obvious use-case that I'm certain we're missing something 🤨 If someone could help point in the right direction... ty!

vilkinsons avatar Oct 13 '22 10:10 vilkinsons

This is also relevant in Next.js 13 with the new Image component

karlhorky avatar Nov 02 '22 11:11 karlhorky