New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature proposal: unsized-media #127

Open
loonybear opened this Issue Jan 16, 2018 · 18 comments

Comments

Projects
None yet
8 participants
@loonybear
Contributor

loonybear commented Jan 16, 2018

The proposal is to add a new feature, unsized-media, which is enabled for all origins by default (default allowlist is *)

When disabled, image or video elements (e.g. <img>, <video>, and <svg>), will be using default dimensions (300 x 150) for unspecified dimensions (width and/or height). This prevents relayout of the image or video elements.

@jpchase

This comment has been minimized.

Contributor

jpchase commented Apr 26, 2018

Please see the explainer for the proposed unsized-media policy.

@annevk

This comment has been minimized.

annevk commented Apr 26, 2018

So is the goal here to change the behavior of how replaced elements are rendered or only when the replaced element is one of the elements mentioned in the document? E.g., would this affect ::before { content:url(/yolo) } or div { content:url(/yolo) }?

@annevk

This comment has been minimized.

annevk commented Apr 26, 2018

How do you get content to jump around with <svg:image>?

@clelland

This comment has been minimized.

Contributor

clelland commented Apr 26, 2018

The high level goal is to avoid having replaced elements with an intrinsic size which gets updated after a network request completes. By declaring that image and video elements have no intrinsic size, the CSS layout algorithms default to 300x150, exactly as they would for an <iframe>, unless some other constraint forces it to the correct size.

content:url() should behave the same way, but I suspect it isn't covered in the proposal at all. I'm not sure if Chrome's experimental implementation handles it -- I'll have to check.

@ojanvafai

This comment has been minimized.

Member

ojanvafai commented Apr 28, 2018

The goal is specifically to be for media (image, video, svg), not all replaced elements. So, content:url isn't affected, nor are form controls. Is that strange?

It's a good question whether we need this for svg:image. I'm not familiar enough with SVG to know if it's possible to have content jumping due to an svg:image loading.

@annevk

This comment has been minimized.

annevk commented Apr 28, 2018

@ojanvafai it seems a little strange architecturally, given where the sizing is done. It seems you need to plumb through the specific element names to the sizing algorithm or invoke a different algorithm at a higher-level. Having said that, perhaps the way CSS describes these things doesn't quite match implementation reality.

@annevk

This comment has been minimized.

annevk commented Apr 28, 2018

(That's also why it's weird <svg:image> is considered, as that doesn't use replaced element sizing, as far as I know.)

@ojanvafai

This comment has been minimized.

Member

ojanvafai commented Apr 30, 2018

I'm not too familiar with implementations other than Blink and WebKit, but neither of those implements intrinsic sizing based off whether the element is replaced or not. Blink (and I believe WebKit) implement these directly in the media elements.

I think the most up to date spec on this is https://www.w3.org/TR/css-sizing-3/#intrinsic-sizes, right? @tabatkins maybe you have thoughts on what the appropriate spec language for this should be and what the <svg:image> behavior should be?

@tabatkins

This comment has been minimized.

tabatkins commented May 1, 2018

It's currently still defined in 2.1 (all the "replaced element" sections in Chapter 10). But that section of Sizing does fill in one explicitly-undefined portion of 2.1, and has a slight behavior change the WG decided on some time ago.

I have no idea what <svg:image>’s sizing behavior is, or what compat constraints might be on it.

However, I do have opinions on how to spec this feature! We would just spec that whatever list of elements this applies to use the CSS default sizing algorithm and pretend that their intrinsic width/height/aspect-ratio is 300px/150px/2:1, rather than sizing as normal per CSS rules.

@clelland

This comment has been minimized.

Contributor

clelland commented May 1, 2018

Thanks, @tabatkins! That's the section I spent this morning looking for again.

The algorithms there, in 10.3.2 and 10.6.2, led me to believe that the spec change for this would be to declare that <img> and <video> elements would have no intrinsic size (height, width or ratio), rather than giving them the intrinsic size of the associated image (and updating that when the image becomes available)

@tabatkins

This comment has been minimized.

tabatkins commented May 1, 2018

Sure, "no intrinsic size" also works, as far as I can tell.

@dbaron

This comment has been minimized.

Contributor

dbaron commented May 1, 2018

One other piece is that this should at least be compatible with future mechanisms that allow specifying what the intrinsic size or aspect-ratio of an image is. (These mechanisms would likely be created to solve the problem that there isn't a way to specify the image's intrinsic size without overriding behaviors that honor the aspect ratio. For example, it would be nice to be able to say something like <img intrinsic-width=300 intrinsic-height=480 style="width: 100%"> and have the resulting height be the one that keeps the image's aspect ratio with the 100% width, rather than the resulting height being 480px.)

In other words, this should only override sizes that would be changed by the process of the image loading and not any others... even if those others are provided by mechanisms that don't exist yet.

@annevk

This comment has been minimized.

annevk commented May 2, 2018

@clelland so <img>.naturalWidth/naturalHeight/naturalRatio (if we add this one at some point) would return 0/0/0 (or null/null/null if we manage to change)?

This would also affect createImageBitmap() and such I think.

Please make sure all such observable aspects have test coverage. (Perhaps making this change by default and running a browser through web-platform-tests you find more aspects that need testing.)

@clelland

This comment has been minimized.

Contributor

clelland commented May 2, 2018

I feel like natural{Width,Height,Ratio} should still be the place where you could introspect the size of the image data, but I could be mistaken there.

I think the HTML spec could call out more clearly the distinction between the intrinsic size of the <img> element, and the intrinsic size of the image contents of that element. The natural* members of Image represent the latter, I think.

My proposal would be to declare that the element has no intrinsic size, when the feature is disabled, in the same way that the <iframe> element has no intrinsic size: even though the document contained in it has a definite size, that doesn't affect the layout of the <iframe>.

@ojanvafai

This comment has been minimized.

Member

ojanvafai commented May 5, 2018

@clelland I don't think exposing naturalWidth/naturalHeight at all works for the intended goal. Then people could still write images that are not sized, wait for it to load, read naturalWidth/Height and set it appropriately, no? So I think @annevk's suggestion or something like it is probably what we'd need to do.

@dbaron yup, that makes sense. In fact, in designing this policy, we stumbled across the need for exposing an intrinsicsize property. Proposal is here: https://github.com/ojanvafai/intrinsicsize-attribute. Feedback very welcome.

@AmeliaBR

This comment has been minimized.

AmeliaBR commented Oct 5, 2018

(I was directed here to weigh in on the interaction with SVG's <image>; not sure if the proposal is still active or if it's waiting on better responsive aspect ratio control in markup.)

My main question: What is the actual goal of restricting this feature? Because that should influence exactly which factors are limited.

If the goal is only to prevent layout from jumping around based on content from untrusted domains, then there's no need to obfuscate the DOM properties. Also, there's no need to worry about <svg:image>, since it's size cannot affect the layout of other elements even when it is auto-sized. (In SVG 2, anyway. If we ever add automatic calculation of the <svg> element's aspect ratio based on its graphical contents, then there would be an indirect effect from an auto-sized image.)

If the goal is to prevent scripts on this domain from being able to exploit the legacy cross-origin security holes that come from being able to read an image's dimensions and confirm that it has correctly loaded, then the more extreme restrictions seem appropriate.

@clelland

This comment has been minimized.

Contributor

clelland commented Oct 5, 2018

Hi @AmeliaBR,
I don't believe that this was originally intended as a security feature at all; the original intention was to stabilize layout by requiring all images to have a size that can be determined by markup / style alone. (Similar to the way that <amp-img> requires width and height to be set)

(And the proposal is still active; this is implemented in Chrome behind a flag, and there's a demo page up at https://feature-policy-demos.appspot.com/unsized-media.html)

@tabatkins

This comment has been minimized.

tabatkins commented Oct 5, 2018

Right, this is purely a "mess me up if I write my page badly, in a way that makes the browser's job easier" feature, like the contain property. No security properties at all.

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