Responsive image preloads multiple sizes

Created on 17 March 2025, about 1 month ago

Problem/Motivation

When the "Responsive image" setting is enabled, two copies of the image are loaded from the network: the correct small image according to the viewport width, and a larger image that is never displayed and slows down the page loading time.

Steps to reproduce

  1. Install the core Responsive Image module
  2. Enable the Blazy formatter on an Image field, and select the "Narrow" responsive image style.
  3. Upload a large image to a page.
  4. When viewing the page, look at the browser network log. Observe that two images were downloaded: the correct one (using the max_325x325 image style), and a large, unused one (using the max_1300x1300 image style).

Proposed resolution

When preloading responsive images, add the sizes attribute so the browser can choose the correct srcset entry to download.

Attached is a patch to the source JS that fixes the issue.

🐛 Bug report
Status

Active

Version

3.0

Component

Code

Created by

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

  • Issue created by @bgreco
  • 🇮🇩Indonesia gausarts

    Thank you.

    ATM, there are three solutions to double downloads:

    • At your Responsive image settings, choose Fallback image _empty_.
    • At Blazy UI, tick Responsive image 1px.
    • At Blazy formatter, choose the smallest image for Image style option.

    More details in each form item description.

    All the three options deal with the image controller aka SRC attribute, ensuring no unnecessary large images are being downloaded which appears to be your OP issue.

    Regarding image SIZES attribute, it is not always present. The sizes attribute is only useful when using the width descriptors. If you're using the display density descriptors, you don't need the sizes attribute.

    Let me know if the solutions fix your issue?

  • Thanks for your suggestions. I tried them, but I'm still seeing the issue. The extra image load isn't coming from the src attribute - it's coming from the srcset.
    Here's my image tag:

    <img decoding="async" class="media__element b-lazy b-responsive b-loaded" loading="lazy"
      srcset="/sites/default/files/styles/max_325x325/public/2025-03/image.png.webp 325w, <-- loaded, correct
              /sites/default/files/styles/max_650x650/public/2025-03/image.png.webp 650w,
              /sites/default/files/styles/max_1300x1300/public/2025-03/image.png.webp 1300w"  <-- loaded, incorrect
      sizes="(min-width: 1290px) 325px, (min-width: 851px) 25vw, (min-width: 560px) 50vw, 100vw"
      width="325" height="185"
      src="/sites/default/files/2025-03/image.png" <-- not loaded
      alt="v">
    

    I didn't realize the sizes attribute might not always be present. Since I am using width descriptors instead of display density, copying the sizes attribute from the original element does help in my case... but maybe it should only be copied if it existed on the original element, instead of falling back to an empty string as I did in my patch?

  • 🇮🇩Indonesia gausarts

    I haven't been able to verify your findings. I hope you understood my previous comment.

    However, feel free to update your patch.

    • add a sizes variable, and wrap your line with a check if the variable exists -- a must,
    • provide the minified version -- optional, I'll do it later if you don't.
  • Thanks, here's the updated patch, not minified yet.

  • 🇮🇩Indonesia gausarts

    I could reproduce your issue, that is, by leaving Image style option empty.

    Meaning you will have original image as the SRC value (says 2000x2000 px, etc.) once 1px placeholder is replaced, while the printed dimension is based on the default Narrow Fallback image Max 325x325 (says 325x217).

    Notice the different dimensions. This might confuse the browsers.

    The good news is this only affects desktop. Fine at mobile, though.

    Existing/ quick solution:

    • Use a smaller Image style at Blazy formatters.

    We also need to correct some logic somewhere due to the current Image style description which allows empty Image style without considering the dimension difference as noted above:

    The content image style. This will be treated as the fallback image to override the global option Responsive image 1px placeholder, which is normally smaller, if Responsive image are provided. Shortly, leave it empty to make Responsive image fallback respected. Otherwise this is the only image displayed. This image style is also used to provide dimensions not only for image/iframe but also any media entity like local video, where no images are even associated with, to have the designated dimensions in tandem with aspect ratio as otherwise no UI to customize for.

    In short, to make Responsive image work correctly with the current logic, without your patch, use a smaller image style, says Thumbnail or hence Max 325x325 to be similar to Narrow default Fallback image. Even when you see two requests at desktop, no real double downloads (different image styles), since the last is the cached version of the same image (one image style).

    Conclusion:
    The actual server-side fix would be to make empty Image style have the value of Responsive image Fallback image style as properly dictated in the description. But that would be for another thread when anyone have a spare time.

    It is no bugs since the solution is there all along.

    However I valued your patch as a client-side enhancement, that is when users leave the Image style empty till the actual fix lands.

    • gausarts committed b24a52af on 3.0.x
      Issue #3513440 by bgreco: Responsive image preloads multiple sizes
      
  • 🇮🇩Indonesia gausarts

    Postponed till the actual fix lands.

    Feel free to contribute on the server-side fix, too.

    Thank you for contribution.

    • gausarts committed 592720d0 on 3.0.x
      Issue #3513440 by bgreco: Responsive image preloads multiple sizes
      
  • 🇮🇩Indonesia gausarts

    The latest fix should make empty Image style fetch the Fallback image as intended in the original description.

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024