nuxt / nuxt/image

`sizes` attribute not working as documented

Open
#1,928 3 comments 3 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
1.5k
Forks
331
Avg merge
19h 52m
Merged PRs (30d)
9

Description

The documentation states that sizes works the same way as tailwind - that is, when you say 'sm:100px', the image will be rendered at 100px at screens sm and larger.

I noticed that this isn't what happens in my case. For context: I'm using the Storyblok provider and have historically never had any issues with sizes having used NuxtImg with Storyblok across multiple builds. There's a high chance I made a mistake somewhere but I've pretty much always used the exact same config.

Bug description:

Passing sizes="100vw sm:50vw" generates an image that's 640px wide on a 13" macbook (pixel density is 2 on this device).
If I pass in a pixel value like sizes="100vw sm:600px" then everything works as expected, and the image is returned at 1200px width, which is correct on this device. If I pass in sizes="100vw sm:50vw md:50vw lg:50vw" then the image is returned at widths closer to correct for these breakpoints.... but it means repeating the same thing for every breakpoint.

If I use, say, 'md:50vw', what is generated ignores pixel density:

<img class="max-w-full max-h-full h-auto object-cover !w-full !h-full" onerror="this.setAttribute('data-error', 1)" width="900" alt="" loading="lazy" data-nuxt-img="" aspect="1.499531396438613" src="https://a.storyblok.com/f/334652/1600x1067/0d3f4ac2c6/643ac16a44a3458afa6a71520927d5252098ef24.jpg/m/768x280/filters:focal(42x49:43x50):quality(80)" sizes="(max-width: 768px) 100vw, 50vw" srcset="https://a.storyblok.com/f/334652/1600x1067/0d3f4ac2c6/643ac16a44a3458afa6a71520927d5252098ef24.jpg/m/1x328/filters:focal(42x49:43x50):quality(80) 1w, https://a.storyblok.com/f/334652/1600x1067/0d3f4ac2c6/643ac16a44a3458afa6a71520927d5252098ef24.jpg/m/2x328/filters:focal(42x49:43x50):quality(80) 2w, https://a.storyblok.com/f/334652/1600x1067/0d3f4ac2c6/643ac16a44a3458afa6a71520927d5252098ef24.jpg/m/384x140/filters:focal(42x49:43x50):quality(80) 384w, https://a.storyblok.com/f/334652/1600x1067/0d3f4ac2c6/643ac16a44a3458afa6a71520927d5252098ef24.jpg/m/768x280/filters:focal(42x49:43x50):quality(80) 768w" height="328">

Reading https://github.com/nuxt/image/issues/1433 , I can see I'm not the only one who doesn't quite get what's happening here.

Expected behavior:

Passing sizes="100vw sm:50vw would generate an image that is 1/2 of the viewport * 2 (in this case 1280) – at xl viewport size, the image width should correspond wi the width of the viewport, not the 'small' viewport (640px).

Context

I suspect SSR might be causing issues if the image is being fetched before the device width is available, but if that's the case, what can be done for images that sit in a responsive grid, and whose width changes every time the viewport is resized.

Here's my config:

  image: {
    provider: 'storyblok',
    storyblok: {
      baseURL: 'https://a.storyblok.com',
    },

    densities: [1, 2],
    format: ['webp'],
    screens: {
      xs: 320,
      sm: 640,
      md: 768,
      lg: 1024,
      xl: 1280,
      xxl: 1536,
      '2xl': 1536,
    },
    quality: 80,
  },

Here's an example of NuxtImg usage:

<NuxtImg
       :src="props.image.filename"
       :width="800"
       :height="328"
       sizes="100vw sm:50vw"
       :modifiers="{ filters: { focal: props.image.focus } }" 
       placeholder
       :alt="props.image.alt"
/>

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the NuxtImg entry point and reproduce the Storyblok configuration with sizes="100vw sm:50vw", densities [1, 2], and the listed screens. Compare the generated sizes and srcset with the expected viewport and pixel-density behavior; done means the responsive output matches the documented sizes syntax without repeating every breakpoint.

Written by the indexing model from the issue text.

Assessment

Tech stack
nuxtjs, typescript
Domain
frontend, performance
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.