Skip to content

sizes=auto images shouldn't use concrete object width to select source #12248

Open

Description

@ltenmoz

What is the issue with the HTML Standard?

Currently, sizes=auto lazy-loading images use the concrete object size width to select which source to use (see step 3.3 here). This can be problematic since the concrete object size can be affected by the image's (intrinsic) aspect ratio. For example, consider

<div style="width: 1000px; height: 100px;">
   <img loading=lazy sizes=auto srcset="small.png 100w, big.png 1000w"
        style="width: 100%; height: 100%; object-fit: contain;">
</div>

The concrete object size of the image is initially 1000x100 before any image loads, so big.png will be selected. Then, supposing big.png has a 1:1 aspect ratio, the concrete object size will shrink to 100x100 to maintain the aspect ratio while fitting in the container due to the object-fit: contain constraint. So now, according to the current spec, small.png must be loaded. This seems wasteful (and could even lead to an infinite loop if small.png had a 10:1 aspect ratio!).
Probably it's best to use the content box width instead, and that seems to be what Blink is doing anyways if I understand correctly: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/css/parser/sizes_attribute_parser.cc;l=148;drc=fa6d7f63f5d366cbe43509c6ded6eb75b16f5088

Activity

  1. emilio commented on Mar 11, 2026

    @emilio
    Contributor

    Yeah so it seems blink is basically doing HTMLImageElement.width or so. Seems reasonable to me.

  2. vinhill commented on Mar 11, 2026

    @vinhill
    Contributor
  3. zcorpan commented on Mar 12, 2026

    @zcorpan
    Member

    So now, according to the current spec, small.png must be loaded.

    No, this is not correct. https://html.spec.whatwg.org/#select-an-image-source-from-a-source-set says

    In an implementation-defined manner, choose one image source from sourceSet. Let selectedSource be this choice.

    An implementation can decide to never downgrade the selected source, i.e. once you've selected big.png 1000w and loaded it, you stick with this selection (until a larger image is needed).

    That said, it's intended that the image's size for the purpose of sizes=auto calculation to be stable before and after loading an image, which is why size containment is forced. I don't recall why "concrete object size" was used instead of the computed content box width, though.

    #9493 changed how this works (but before also used concrete object width); points to #9448

  4. noamr commented on Oct 5, 2026

    @noamr
    Contributor

    Somewhat relevant comment on the original sizes=auto discussion: #4654 (comment)

    There is also the inverse problem - object-fit: cover might fetch an image that's too small, and scale it to fit the object area.
    Seems like what we really need is to find a comprehensive solution for 2D-base auto-sizing?

  5. zcorpan commented on Oct 5, 2026

    @zcorpan
    Member

    https://drafts.csswg.org/css-images/#the-object-fit changes the concrete object size, so maybe this is why we used it for sizes=auto. The example in OP doesn't use width and height attributes which are recommended in the spec, and would give an aspect ratio I think.

    cc @whatwg/css

  6. noamr commented on Oct 6, 2026

    @noamr
    Contributor

    From what I understand, object-fit makes the concrete size of the image depend on two things:

    a) The width/height of the container (which can be defined by the image's width/height attributes)
    b) The intrinsic aspect ratio of the image (to account for cover and contain etc)

    (b) can only be derived from an image that is already fetched.

    This creates a circular dependency - as re-fetching the image might bring an image with a different aspect ratio. I don't think this re-fetching is spec'ed. So implementations mostly short-circuit this and assume that the image's width/height attributes also define the aspect ratio.

    Are we recommending that authors use the natural width/height (or at least the natural aspect ratio) in the attributes and then correct it to the displayed size with CSS?

  7. noamr commented on Oct 7, 2026

    @noamr
    Contributor

    That said, it's intended that the image's size for the purpose of sizes=auto calculation to be stable before and after loading an image, which is why size containment is forced. I don't recall why "concrete object size" was used instead of the computed content box width, though.

    Yea that makes size containment insufficient because size containment does not affect the post-loading concrete size in the contain/cover cases.

    We should probably go with the content box as suggested here and as implemented in blink.
    Separately, we should find a way to allow authors better control so that they can load crisp images with object-fit, e.g. let them specify the natural aspect-ratio in advance.

  8. noamr commented on Oct 7, 2026

    @noamr
    Contributor

    Some more concrete proposal:
    Why don't we use the h value (currently specced as future-compat-h as a hint for defining a natural aspect ratio?
    Then when selecting a source, we can take that together with w to mean the expected aspect ratio, and then use it in conjunction with the image's computed object-fit to compute a more appropriate source. This would still re-select a source if the object-fit changes, but only based on the aspect ratios in srcset and not based on the image content.

    WDYT?

    cc @austinh

  9. austinh commented on Oct 7, 2026

    @austinh

    WDYT?

    cc @austinh

    +1, this would solve a real problem for us. At Airbnb most listing photos render with object-fit: cover in fixed-ratio boxes, and the photos are usually wider than the box. Content-box selection alone under-fetches: a 4:3 photo in a 1:1 card is drawn at 1.33x the box width, so it looks soft. A fixed per-image correction doesn't hold up either, because the box's aspect ratio changes across breakpoints and photos in the same grid have different ratios. w/h lets the UA work it out from the real layout. Our CDN/backend already knows source dimensions when it builds srcset, so emitting h costs us nothing.

    Some thoughts:

    • The hint wins after load: if the fetched image's real ratio differs from w/h, don't re-select. That keeps selection independent of image content and rules out loops. It's probably also worth saying whether w/h are in post-EXIF-orientation terms.
    • Eager images: this only helps sizes=auto. Above-the-fold images with explicit sizes are chosen by the preload scanner before layout, so they'd still under-fetch with cover. Is there anything we could do there, e.g. letting authors declare the box ratio up front? (this is where my densityscale proposal comes in handy)
  10. noamr commented on Oct 7, 2026

    @noamr
    Contributor

    WDYT?
    cc @austinh

    +1, this would solve a real problem for us. At Airbnb most listing photos render with object-fit: cover in fixed-ratio boxes, and the photos are usually wider than the box. Content-box selection alone under-fetches: a 4:3 photo in a 1:1 card is drawn at 1.33x the box width, so it looks soft. A fixed per-image correction doesn't hold up either, because the box's aspect ratio changes across breakpoints and photos in the same grid have different ratios. w/h lets the UA work it out from the real layout. Our CDN/backend already knows source dimensions when it builds srcset, so emitting h costs us nothing.

    Some thoughts:

    • The hint wins after load: if the fetched image's real ratio differs from w/h, don't re-select. That keeps selection independent of image content and rules out loops. It's probably also worth saying whether w/h are in post-EXIF-orientation terms.

    Right! It has to be post-EXIF I think.

    • Eager images: this only helps sizes=auto. Above-the-fold images with explicit sizes are chosen by the preload scanner before layout, so they'd still under-fetch with cover. Is there anything we could do there, e.g. letting authors declare the box ratio up front? (this is where my densityscale proposal comes in handy)

    Perhaps we should allow somtehing like <img sizes="cover 300px 200px"> for the eager version, in conjunction with the h descriptor.

  11. noamr commented on Oct 8, 2026

    @noamr
    Contributor

    To summarize the proposal:

    • h descriptor (currently ignored) is taken into account to compute a source aspect ratio before fetching. The source aspect ratio defaults to the image's width/height attributes for sources with no h.
    • In loading=eager sizes=auto mode, the source aspect ratio together with the computed object-fit and the content box are used to compute the source concrete width (which is the expected concrete size if the image content matches the descriptor).
    • In loading=eager mode, the 2D area and fit can be put directly in the sizes attribute, with a fallback after the comma: <img sizes="cover 300px 100vh, 300px">
    • Changing the content box or object-fit are relevant mutation for selecting a new source. Changing the concrete size is not, as it can be affected by the image content.
    • The source concrete width can be used by the browser for source selection (though that's somewhat implementation defined)
  12. zcorpan commented on Oct 8, 2026

    @zcorpan
    Member

    Also see #3981

  13. zcorpan commented on Oct 8, 2026

    @zcorpan
    Member

    @noamr the width and height attributes set aspect-ratio in the UA stylesheet. I think the intent is indeed that they should be used to "set" the aspect ratio, and you can override the box dimensions with CSS.

    We can maybe still add the h descriptor, but then I think the purpose should be to improve resource selection rather than only set aspect ratio.

  14. noamr commented on Oct 8, 2026

    @noamr
    Contributor

    @noamr the width and height attributes set aspect-ratio in the UA stylesheet. I think the intent is indeed that they should be used to "set" the aspect ratio, and you can override the box dimensions with CSS.

    aspect-ratio doesn't help because it sets the container aspect ratio and not the image aspect ratio considering object-fit.

    We can maybe still add the h descriptor, but then I think the purpose should be to improve resource selection rather than only set aspect ratio.

    Yes, the idea here is that h only improves source selection and doesn't affect the resulting aspect ratio.

  15. added
    agenda+To be discussed at a triage meeting
    on Oct 8, 2026
  16. foolip commented on Oct 8, 2026

    @foolip
    Member

    What would the syntax be? Something like srcset="small.png 100w 50h, big.png 1000w 500h"?

  17. removed
    agenda+To be discussed at a triage meeting
    on Oct 8, 2026
  18. noamr commented on Oct 8, 2026

    @noamr
    Contributor

    What would the syntax be? Something like srcset="small.png 100w 50h, big.png 1000w 500h"?

    Yes.

    Plus the sizes="cover 300px 100vw" thing for eager images.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions