Image component `sizes` property does not work
See original GitHub issueBug report
Describe the bug
When using the Image component, the sizes
property doesn’t work as described in the docs.
When using the Image component, the image is resized to match the container width which is size of the width
attributes that we passed, or fit 100% of the viewport if the image is larger than the screen, ignoring the sizes
attribute completely.
Example of code:
<Image
width="800px"
height="456.8px"
sizes="(max-width: 500px) 100px"
src="/next.png"
alt="Next.js"
/>
To Reproduce
I created a codesandbox example with the exact problem:
- Go to https://codesandbox.io/s/elated-neumann-u81mr?file=/pages/index.js
- Resize the browser window width to be bigger than 500px to see that the image is the size of
width 800px
andheight 456.8px
- Resize the browser window width to be smaller than 500px to see that the image will fit to 100% of the screen, not respecting the
sizes
prop that should tell the image to be100px
Expected behavior
I expect the image to have exactly a 100px when the view port is smaller then 500px, respecting the sizes attribute.
Screenshots
Bigger viewport width
Smaller viewport width
System information
- OS: Ubuntu 20.04
- Browser: Chrome
- Version of Next.js: 10.0.0
- Version of Node.js: v12.18.3
Issue Analytics
- State:
- Created 3 years ago
- Reactions:16
- Comments:47 (8 by maintainers)
Top Results From Across the Web
How to use Image component in Next.js with unknown width ...
The idea: get size of image when it's loaded, calc the ratio and use it to make the container fill the require space...
Read more >Nextjs image optimization with examples - Refine Dev
The sizes prop only works for images with layout="responsive" or layout="fill" .
Read more >next/image - Next.js
The sizes property allows you to tell the browser that the image will actually be smaller than full screen. If you don't specify...
Read more >The Media or Image Source element - HTML - MDN Web Docs
A list of source sizes that describes the final rendered width of the image represented by the source. Each source size consists of...
Read more >@astrojs/image Astro Documentation
This is the helper function used by the <Picture /> component to build multiple sizes and formats for responsive images. This helper can...
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Can we get this re-opened? If I’ve understood correctly, I don’t believe this is resolved.
The image component is incredible and a brilliant idea, but it seems responsive images are not behaving as expected.
When comparing @josepholiveira’s example here -
To a pure html example, they should behave the same shouldn’t they?
Heres a codesandbox with both a next.js and html example side by side, trying to load the same size responsive images - https://codesandbox.io/s/empty-morning-4gdp9?file=/pages/index.js
The html example is inline with the way the expected behavior quoted above by @josepholiveira, in that it is supplying a 100px image.
The Next.js example loads a 320px image (as seen in network tab), and ignores the sizes request of a 100px image. (I’m also not sure why its 320, as that value is not present in deviceSizes or imageSizes).
I know when using layout=“responsive” next.js automatically supplies images that are sized based on the viewport, those images are at the following sizes: 640, 750, 828, 1080, 1200, 1920, 2048, 3840..
But is this ignoring of a requested size in the
sizes
prop intentional? Why could the image component not supply a 100px sized image? Loading a 320px image, that is 3.2x bigger than needed feels like a big hit to performance.Maybe I am misunderstanding how responsive images or how the image component works, apologies if so. Thanks again for the great work! 😃
Thanks to @josepholiveira @styfle @AshConnolly & @LauraBeatris for your contributions here.
I finally understand how to use the sizes prop with Next.js. Here’s the simple explanation.
Can I add this to the docs via a separate pull request?
---------------------- ---------------------- ----------------------
Need a smaller size? Just specify a smaller visual width. The default is 100vw, meaning 100% of the viewport. For a 3-column layout, try 33vw – the closest image to 33% of the viewport will get served. You can also use media queries to get specific with your responsive image sizes. Don’t forget to add additional deviceSizes in next.config.js if you need sizes <640px for mobile devices. Otherwise, 640px will be the smallest size Next.js can serve. For convenience, you can specify a custom deviceSizes by simply adding the default imageSizes array (which goes down to 16px) before the default deviceSizes.
Once you add that code, you can conveniently use any small vw value (like 10vw) and know that there will always be an appropriate version on tiny mobile devices. The smallest served will be 16px, and you’ll have a total of 17 responsive image sizes served automatically by Next.js v10 or later.
---------------------- ---------------------- ----------------------
And here’s a bunch more info in case anyone finds this issue while searching online like I did.
Here’s an example that can be used with this Next.js + Tailwind CSS starter blog https://jamstackthemes.dev/theme/nextjs-tailwind-starter-blog
That starter blog has a nice overview of using Images in Next.js 10 here: https://tailwind-nextjs-starter-blog.vercel.app/blog/guide-to-using-images-in-nextjs
Unfortunately it’s not clear what to do with a layout=“fill” image that won’t fill the entire viewport, without reading the MDN docs several dozen times.
(This obvious “use a sizes value of 33vw for an image in a 3-column grid” example does not appear in the MDN docs.)
Here’s a basic example of a small responsive image using 33vw (33% of the visual width of the device’s viewport):
index.js
Here’s a full 3-column gird layout example that also has a long description of how you can use media queries in the string you pass as the “sizes” prop:
index.js
And here’s my Next.js config file:
next.config.js
Hope this helps someone. And @styfle if you approve I’ll open a pull request to make the changes to the docs. I don’t want to do it right this second, because I could be entirely wrong here 😅