html icon indicating copy to clipboard operation
html copied to clipboard

Allow `<source>` elements to query container sizes

Open andy-blum opened this issue 1 year ago • 8 comments

What problem are you trying to solve?

HTML's <source> elements are able to query viewport width with the media attribute to swap image sources based on device size. Now that container queries are part of Baseline 2023, <source> attributes should be able to swap image sources based on the size of a parent container as well

What solutions exist today?

DIY JavaScript solutions can alter the src attribute of <img> elements, but this still requires the rapid-fire callbacks of a resizeObserver to handle. JS-based solutions could be improved with a window.matchMedia analog for container queries as proposed here, but a native HTML solution would be ideal.

How would you solve it?

Similar to the existing media attribute, a new container attribute would be added and its value used to query the inline size of a container. This would query the width of the containing picture element to select the preferred source.

<picture>
  <source srcset="image-wide.png" container="(width > 800px)" />
  <source srcset="image-medium.png" container="(width > 600px)" />
  <img src="image-narrow.png" alt="alt text" />
</picture>

Alternatively, the container could also accept a <container-name> value that's been defined in CSS to instead query some container higher in the DOM.

<picture>
  <source srcset="image-wide.png" container="component (width > 800px)" />
  <source srcset="image-medium.png" container="component (width > 600px)" />
  <img src="image-narrow.png" alt="alt text" />
</picture>

Anything else?

No response

andy-blum avatar Mar 06 '24 14:03 andy-blum

Wouldn't this make the image wait on the page for layout?

myakura avatar Mar 06 '24 14:03 myakura

It would, but that's not a problem for lazy-loaded images or other images that are farther down the page.

andy-blum avatar Mar 06 '24 14:03 andy-blum

Similar discussion happening here: https://github.com/w3c/csswg-drafts/issues/5889

andy-blum avatar Mar 06 '24 15:03 andy-blum

I can see future in which

<picture>
  <source container="(width > 500px)" srcset="a">
  <img loading="lazy" src="b">
</picture>

works. But:

  1. I think there are a lot of important, unanswered questions in the CSSWG thread about the performance impacts of this pattern. Anecdotally, I feel like art direction is especially used for above-the fold, hero/LCP images. And the only way out that I can see there - sizes on every ancestor container, worries me on a number of levels.
  2. What should happen here?
<picture>
  <source container="(width > 500px)" srcset="a">
  <img src="b">
</picture>

My first take is, if source elements use container (or whatever) but the img does not have loading=lazy, the container query ("container condition"?) always evaluates to false.

eeeps avatar Mar 06 '24 15:03 eeeps

Related: https://github.com/whatwg/html/issues/8007

zcorpan avatar Mar 18 '24 21:03 zcorpan

@andy-blum your solution needs to wait for the layout of the page. At this point, there is no actual benefit in providing media queries at all. A sizes="auto" could be added that just selects the correct image without having to specify any query at all.

enyo avatar Feb 18 '25 09:02 enyo

@enyo The use case here is not viewport-based-selection, but rather art-direction. sizes=auto and srcset are not sufficient for art direction because they don't give the author any guarantees about which variant will be selected, when.

eeeps avatar Feb 18 '25 17:02 eeeps

I encountered a use-case I could have solved with a container condition on a <source> element; and wish to add that the feature should not just allow container size queries but also container style queries. My use-case: Switch the image source URL via a custom CSS variable used as a flag In my case it is a dark-mode variant and a light-mode variant of the image; but using <source media="(prefers-color-scheme: dark)" ...> is not solving it for me because I need fine control whether parts of the page are shown in the dark-mode styles or not; some parts of the page are always showing their light-mode variant.

<picture>
  <source srcset="icon-darkmode.svg" container="style(--dark-mode)" />
  <img src="icon-lightmode.svg" alt="alt text" />
</picture>

teetotum avatar Dec 04 '25 12:12 teetotum