WICG / intrinsicsize-attribute

Proposal to add an intrinsicsize attribute to media elements
Apache License 2.0
93 stars 14 forks source link

Relationship to responsive image features #3

Open eeeps opened 6 years ago

eeeps commented 6 years ago

Right now, srcset w descriptors set the intrinsic width of the image.

There was a lot of talk back in the day about adding an h descriptor, which would – in addition to allowing browsers to select sources for images whose layout size is constrained on height – set the intrinsic height of the resource.

Does this proposal have any advantages over this (which was proposed but not yet spec'd or implemented):

<img srcset="image.jpg 600w 400h" />

?

I can see some disadvantages.

  1. It is more verbose, even in simple non-responsive cases.
  2. In responsive cases, It is not clear how intrinsicsizes would allow for different intrinsic sizes for the different resources in a srcset or <picture>. Where do the intrinsicsizes go, and what should they be, on either of these images?
<img srcset="300x200.jpg 300w, 600x400.jpg 600w, 800x533.jpg 800w" />
<picture>
   <source
      media="(max-width: 600px)"
      srcset="cropped-square-sm.jpg 600w, cropped-square-lg.jpg 1200w"
      sizes="100vw" />
   <img
      srcset="full-16x9-sm.jpg 800w, full-16x9-med.jpg 1400w, full-16x9-lg.jpg 2000w"
      sizes="100vw" />
</picture>

In cases where intrinsicsize contradicts w descriptors, what happens?

loonybear commented 6 years ago

Yea I am trying to think in the case when there are different aspect-ratio wanted for responsive images, how can we achieve so by intrinsic-size attribute.

tigt commented 6 years ago

srcset images shouldn't differ in aspect ratio, right? I thought that was an implicit requirement, or undefined browser behavior kicks in.

tigt commented 6 years ago

That is, <picture> and multiple <source>s should be used if the aspect ratio changes responsively.

eeeps commented 6 years ago

@tigt yup! You might have small changes because of rounding (3000×2000 → 188×125), dunno if those would ever matter? But per spec, srcset should be used:

to provide multiple images that only vary in their size (the smaller image is a scaled-down version of the bigger image)

https://www.w3.org/TR/html/semantics-embedded-content.html#embedded-content-introduction

If the aspect-ratio is changing in non-scaling-rounding related ways (e.g., 16:9 → 1:1), use multiple <source>s

loonybear commented 6 years ago

My bad. I didn't know the aspect-ratio would remain the same.

However, I have a different opinion in terms of which solution is cleaner:

  1. Since the aspect-ratio remains the same, it seems cleaner and easier to understand by specifying it in "intrinsic-size" attribute than implicitly specifying it everywhere in "srcset".
  2. Re "it is not clear how intrinsicsizes would allow for different intrinsic sizes for the different resources in a srcset or ": I believe in this case, intrinsic-size will specify the aspect-ratio / intrinsic-ratio, and the width provided in srcset will be used as the width for the image.

In addition, from an implementation's perspective, "intrinsic-size" attribute will be easier to parse ([number] x [number], and always in px unit). The logic is easier to implement and understand too. Adding an 'h' dimension sounds great and comprehensive, but it does add some complication, to both web dev and browser dev to interpret.

Apologies in advance for my inexperience in web dev or any misunderstanding of this issue.

eeeps commented 6 years ago

Just saw your Intent to Implement on this, @loonybear. Thank you for pushing it forward!

Let me check my understanding of the explainer. I’m worried that things might get a little weird and/or complicated re: intrinsic sizes and responsive images. Consider the following markup:

<img
     intrinsicsize="16x9"
     srcset="small.jpg 640w, medium.jpg 960w, large.jpg 1024w, extra-large.jpg 1280w"
     sizes="100vw"
/>

Let's say the user agent picks extra-large.jpg out of this srcset. Without any extrinsic sizing acting on this image, what will its rendered size be?


I think the intent is that it would render at 100vw×56.25vw, matching the current behavior, without intrinsicsize).

However, given the current kinda-vague language in the explainer, I worry...

w descriptors and sizes are used to set the intrinsic density of the image, which is applied to the intrinsic dimensions to get the density-corrected intrinsic dimensions – which are used to layout/paint.

I think the above image has:

So! Given the language of the explainer and my current understanding of the spec, I worry this markup in this context will render at 8px×4.5px, rather than the 640px×360px that it would, now, without intrinsicsize.

This seems bad. Am I missing something?

nhoizey commented 6 years ago

I agree with @eeeps here, and as a Web developer, I would prefer an intrinsicratio (or just ratio) attribute, to prevent such worries.

loonybear commented 6 years ago

intrinsicsize will work as an intrinsic ratio when it comes to responsive images. Please refer to this example to see why ratio / intrinsic ratio might not work well.

@tabatkins and I talked about the possibilities of modifying how responsive images determine intrinsic dimensions based on the "intrinsicsize" attribute. He might have more thoughts on how it will work with intrinsic density.

loonybear commented 6 years ago

Hi,

I was looking at how responsive images calculates its source size , and I think the algorithm below would make "intrinsicsize" work well with responsive images:

The “Intrinsicsize” attribute sets the image’s intrinsic aspect ratio, and the intrinsic width and height equivalent to descriptor ‘1x’. For an \<img> element with a srcset, if:

@yoavweiss, @tabatkins, @clelland

tabatkins commented 6 years ago

For #2, intrinsic dimensions here are post-density correction, so there's no need to invoke density at all here. The value specified in intrinsicsize gives the intrinsic dimensions.

Also, sizes does nothing at all when using the x descriptor. It's sole effect is to help translate a w descriptor into an equivalent x (which then has the effect of setting the image's intrinsic width to the length specified in sizes, but that's purely a roundabout side-effect, not a direct assignment).

So, you can just collapse away the second bullet point entirely and just rely on the first and third.

eeeps commented 6 years ago

So basically: intrinsicsize always sets the density-corrected intrinsic size, unless it’s on an <img> whose currentSrc had a w attached to it. In that case, intrinsicsize sets the intrinsic aspect ratio only, and the density-corrected intrinsic width is calculated in the same way that it is now (intrinsic width = w, density = w÷sizes, density-corrected intrinsic width = intrinsic width ÷ density).

Sounds workable? I’ve got a question about how this might interact with Client Hints, but I’ll spin up another thread for that. A couple of markup-focused follow-ups:

  1. will this awkwardly interfere with h in any way, if that does end up getting spec'd? intrinsicsize would solve the intrinsic-height use case for h, but not the height-constrained-selection use case. I don’t want to let the perfect be the enemy of the good; I also don’t want to make height-based selection super hard or weird to solve, later.
  2. what to we do with <picture> and multiple <source>s? Maybe it’s as simple as allowing intrinsicsize on <source>— and if a <source> feeds an <img> a resource, it sends the intrinsicsize along with it.
tabatkins commented 6 years ago

Yes. I think that's the most reasonable interpretation here, as it preserves the full meaning of intrinsicsize as much as possible; the one exception is just because otherwise sizes/w loses meaning.

will this awkwardly interfere with h in any way, if that does end up getting spec'd?

I don't think so. Either we allow both w and h on a single element, and it fully overrides intrinsicsize, or we allow only one of them, and intrinsicsize continues contributing a ratio.

what to we do with picture and multiple sources? Maybe it’s as simple as allowing intrinsicsize on source— and if a source feeds an img a resource, it sends the intrinsicsize along with it.

That's exactly what we do, yes. If <source intrinsicsize> isn't already written into the proposal, that's just an accidental omission.

loonybear commented 6 years ago

Sounds good, I am currently planning to ship intrinsicSize on and

eeeps commented 6 years ago

Just to close the loop, for the two examples in the OP...

<img srcset="300x200.jpg 300w, 600x400.jpg 600w, 800x533.jpg 800w" sizes="100vw" intrinsicsize="3x2" />
<picture>
   <source
      media="(max-width: 600px)"
      srcset="cropped-square-sm.jpg 600w, cropped-square-lg.jpg 1200w"
      sizes="100vw"
      intrinsicsize="1x1"
   />
   <img
      srcset="full-16x9-sm.jpg 800w, full-16x9-med.jpg 1400w, full-16x9-lg.jpg 2000w"
      sizes="100vw"
      intrinsicsize="16x9"
   />
</picture>

@ojanvafai, does any of this need to be captured in the explainer, or can it wait until there's a spec?

MattWilcox commented 5 years ago

Can't delete, sorry. Mesage above answered my question.

loonybear commented 5 years ago

Yes, they will be in spec.

mathiasbynens commented 5 years ago

It's common to provide 2x images for high-DPI screens, as follows:

<img src="foo.png" srcset="foo@2x.png 2x" width="100" height="100" intrinsicsize="??">

In this case, the intrinsic size of foo.png is 100x100, and the intrinsic size of foo@2x.png is 200x200, although either of them would take up 100x100px when rendered (even if the width/height attributes were omitted). What should the intrinsicsize attribute value be in this scenario? (I'm assuming it should be 100x100.)

Update: The “How does this work with responsive images?” seems to cover this already, but it would be great to mention this common pattern explicitly in the README/FAQ.

tabatkins commented 5 years ago

In this case, the intrinsic size of foo.png is 100x100, and the intrinsic size of foo@2x.png is 200x200

You're misusing terms. ^_^ The "intrinsic size" is what size it will naturally take up on the page, absent any CSS fiddling with it. In both cases, that size is 100px×100px (assuming that the 1x image is indeed 100×100 image pixels), because density correction is part of determining how something "naturally" lays out. (I don't think we have an agreed-upon term for "size in image pixels", so it's understandable that talking about this is a little awkward.)

Note that, in your example, intrinsicsize is irrelevant, since width and height attributes are already fully specifying its size. But if we pretend those weren't specified, then intrinsicsize="100x100" is what you probably want to say.

domenic commented 5 years ago

Note that, in your example, intrinsicsize is irrelevant, since width and height attributes are already fully specifying its size.

Yeah, I think we might need a dedicated section guiding people not to spam this on all their images, and to use width=""/height="" instead when possible. intrinsicsize="" only makes sense to use when you plan to use non-pixel widths/heights via CSS.

mathiasbynens commented 5 years ago

intrinsicsize="" only makes sense to use when you plan to use non-pixel widths/heights via CSS.

Yes, but doesn’t this apply to the common pattern of img { max-width: 100%; height: auto; } as well? I’d imagine every modern website has this line of CSS.

(I’m honestly asking — if I misunderstood, I have a PR to revert 😅)

frank-dspeed commented 5 years ago

@mathiasbynens i don't got such lines in my css i am wondering how you can think that it would be existing that often. Today People have some Fixed behavior for every screen Model. Most even resize images to fit for the targeted Screen so they work even without size Attributes

eeeps commented 5 years ago

@domenic What's the downside to intrinsicsize attributes on every <img> on the web? What's the benefit of height=100 width=100 vs intrinsicsize=100x100?

Seems like we should try to depreciate height + width and encourage intrinsicsize, which accomplishes the same thing (pre-allocating layout space for the image, reducing jank), but plays nicer with fluid-size + fixed-aspect-ratio imagery.

tabatkins commented 5 years ago

(deleted previous post because it was wrong, sorry people following on in email!)

Yeah, there's no benefit to sending width=100 height=100 over intrinsicsize=100x100. They'll act the exact same in the absence of CSS, and in the presence of CSS, the latter will maintain the intended aspect ratio at all times and without extra effort. (On the other hand, if you use width/height attributes, and then CSS only sets width: 100%, then the height will stay at 100px, which probably isn't what you wanted...)

mathiasbynens commented 5 years ago

@tabatkins

Re:

<img src="foo.png" srcset="foo@2x.png 2x" width="100" height="100" intrinsicsize="100x100">

Note that, in your example, intrinsicsize is irrelevant, since width and height attributes are already fully specifying its size. But if we pretend those weren't specified, then intrinsicsize="100x100" is what you probably want to say.

Does your answer change if the CSS img, video { max-width: 100%; height: auto; } applies to the image?


@ojanvafai @loonybear It would be highly valuable to add a clear mental model to the explainer, answering the question:

When should I use width/height, when should I use intrinsicsize, and when (if ever) should I use both?

It'd help to get explicit guidance specifically for the following situations:

tabatkins commented 5 years ago

Does your answer change if the CSS img, video { max-width: 100%; height: auto; } applies to the image?

Yes. width/height are equivalent to intrinsicsize in the absence of any other CSS changing the size. If there is additional CSS, intrinsicsize gives better behavior, as it lets us respect the aspect ratio before loading the image.


For the rest of your comment, yes, if HTML is the only source of sizing info, using width/height makes more sense for now, because of limited support for intrinsicsize. Once intrinsicsize is more widely supported, there's no real reason to use width/height, even in HTML-only situations.

If there's any CSS at all, intrinsicsize is the way to go.