Skip to content
This repository has been archived by the owner on Jan 9, 2020. It is now read-only.

A more elegant and easier to use solution #16

Open
jensimmons opened this issue Jun 6, 2019 · 87 comments
Open

A more elegant and easier to use solution #16

jensimmons opened this issue Jun 6, 2019 · 87 comments

Comments

@jensimmons
Copy link

jensimmons commented Jun 6, 2019

The CSS Working Group is working on a solution to this problem.

The HTML for web developers will look like this:

<img src="dog.jpg" width="400" height="300">

The UA-stylesheets of all browsers will add this code:

img, video {
    aspect-ratio: attr(width) / attr(height);
} 

This will calculate an aspect ratio, based on the width & height attributes — before the image has loaded — and have that information available at the very beginning of layout calculation. The moment an image is told to be width: 100%, for example, the aspect ratio is used to calculate the height.

There is no need for a web developer to do anything else, or anything new (besides return to the habit of using width and height attributes in HTML for a performance gain). It'll just happen.

We are implementing this in Firefox as an experiment, in part to make sure such a solution will not break existing websites.

@scottjehl
Copy link

👍 Big fan of this proposal, particularly if the CSS ends up in the browser's UA stylesheet so that old and new sites gain aspect ratios on their images with little or no work.

@chriscoyier
Copy link

I'm into it. Seems like a fantastic idea.

I like blogging so I blogged it.

@JoshTumath
Copy link

This is such a great idea! Hopefully, this can help with the proposed HTML loading attribute, as well (whatwg/html#3752). The attribute is designed to prevent making a network request for an image or iframe until it is scrolled into view. However, Chrome's implementation still makes a small request for the first few bytes of the image to get its dimensions. If this rule is added to the UA stylesheet and the author has specified the width and height attributes, Chrome would not need to do its metadata prefetching.

Speaking of iframes, would it make sense to include iframe in this CSS rule? Websites that use iframes to embed videos or animated gifs from other websites like YouTube would be able to scale while maintaining the aspect ratio, too.

@scottjehl
Copy link

I agree. iframe would be nice, as would object.

@simevidas
Copy link

Is it safe to assume that the aspect ratio computed from the image’s width and height attributes will always be the same as the aspect ratio of the rendered image after it loads and is styled by the page’s CSS?

@nuxodin
Copy link

nuxodin commented Jun 7, 2019

As much as I like that proposal:
If I don't make a memorial mistake, this will break the web.
Today, this will squeeze/deform the image, the height stays at 572px:

<div style="width:200px">
  <img width="960" height="572" src="image-960x572.jpg" style="width:100%">
</div>

https://jsfiddle.net/tpgn143f/4/

According to this proposal, the height will be calculated from the aspect ratio.

@michaelwhyte
Copy link

I am concerned about this idea. For years since we have been building responsive fluid web layouts declaring width and height attributes on "img" elements could be problematic when the actual size of an image as displayed on the page is basically unknown and fluid.

Unless the developer takes the time to set up their CSS correctly, images could become squished or stretched if the width and height attributes are present on the image tag. Plus, sometimes we want our images to be displayed at a different aspect ratio then actual aspect ratio of the image itself (with the help of object-fit). Finally, there is the "picture" element and art directing of images, sometimes we want a square-crop on mobile and landscape crop on desktop, these are two very different aspect ratios.

I guess I am saying many sites and developers have been omitting the width and height attribute on images for a while. We would now have to make sure everyone put them back in, and then it is not always appropriate to do so.

@Sora2455
Copy link

Sora2455 commented Jun 7, 2019

@michaelwhyte If I understand this correctly, this rule would have no effect on images without width and height attributes, leaving their behaviour unchanged.

@nuxodin
Copy link

nuxodin commented Jun 7, 2019

@jayhostan True, it would be necessary to set the CSS height to auto.
So it would not break the web.

Also, it would not be possible to polyfill this without an additional custom-property --aspect-ratio or manually parsing the stylesheets.
https://github.com/nuxodin/intrinsicsize-polyfill

But yes, I see that the proposal has the big advantage that you don't need an additional attribute.
And above all, we have the long-awaited aspect-ratio for other things as well!

@yoavweiss
Copy link
Collaborator

@ojanvafai @loonybear @dvoytenko - Thoughts?

@yoavweiss
Copy link
Collaborator

Also, @kinu & @domfarolino for lazy loading and range request downloads.

@chrisg88
Copy link

chrisg88 commented Jun 7, 2019

Is attr() no longer experimental outside of pseudo content?

@fantasai
Copy link

fantasai commented Jun 7, 2019

The aspect ratio calculated from the width and height HTML attributes won't have any effect unless the author has explicitly set at least one of the width or height CSS properties to auto. Therefore the only case where this proposal can result in a change in rendering is if the author has both: a) set incorrect width/height values in the HTML and b) set one of the image's dimensions to auto in the CSS. Furthermore if that situation happens to be a Web-compat problem, we can change the priority so that the image's own aspect ratio wins over the declared one once it is loaded.

Is attr() no longer experimental outside of pseudo content?

If we decide to go down this route, the mapping will probably be handled at the CSS presentational hint layer (in C++) where presentational attribute-to-CSS mappings happen, rather than using CSS syntax in the UA style sheet directly; as far as I'm aware we still don't have implementations of attr() outside content. But the effect would be equivalent.

@ojanvafai
Copy link
Member

The aspect ratio calculated from the width and height HTML attributes won't have any effect unless the author has explicitly set at least one of the width or height CSS properties to auto.

Can you explain this more? Why does it require the author to explicitly css the width/height CSS properties to auto to hit the issue?

Furthermore if that situation happens to be a Web-compat problem, we can change the priority so that the image's own aspect ratio wins over the declared one once it is loaded.

How would this work? It sounds like you're saying the aspect-ratio CSS property would not do anything to elements that have an intrinsic aspect ratio once loaded?

@ojanvafai
Copy link
Member

Also, for others, here's the previous CSSWG discussion about this https://lists.w3.org/Archives/Public/www-style/2019Mar/0015.html and #4 (comment) seems like relevant data depending on the explicitly set to auto thing.

@Sora2455
Copy link

Sora2455 commented Jun 7, 2019

@ojanvafai The aspect-ratio property only has meaning when one of height or width is set to auto - then it adjusts that automatic height/width to fit the aspect ratio.

I've set up a test fiddle: https://jsfiddle.net/Sora2455/Lw5mob1d/. This change will only affect the last example, if I've understood this correctly.

@VishnuBaliga
Copy link

Big fan of this fantastic idea!

@bkardell
Copy link

Discussing this during in-betweens at the csswg f2f it seemed to me that @tabatkins had thoughts here that he might express? One thing that I was asking several people about is that it seems clear that there is a rasterizing step here and a change of the reported .naturalHeight and .naturalWidth that is unique to this proposal. I'm not 100% clear on the intent of this, but it does seem that the two proposals actually accomplish different things and it would be good to explain why this was necessary - because if it is, it seems very relevant. Having both, it seems, are not really at odds - just more complicated.

@dvoytenko
Copy link

@yoavweiss @ojanvafai @jensimmons If the aspect-ratio and attr() (outside the content context) CSS were wide-spread, I see this as a great idea. I'd not even necessarily see a need to have the aspect-ratio: attr(width) / attr(height); in the user stylesheet immediately. I'd be more than happy, in the user land, to do something very similar, e.g.:

img, video, .aspect-ratio, ... {
  aspect-ratio: attr(width) / attr(height);
  object-fit: contain;
}

@yoavweiss
Copy link
Collaborator

The bits that are not clear to me about this solution is how it would be something deployable assuming that not all browsers out there support the new aspect-ratio scheme.

e.g. looking at https://steady-jellyfish.glitch.me/, it seems like a non-supporting browser (e.g. all of them right now) will display responsive images very differently depending on their set width and height values.

@fantasai - am I missing something here? Or were your comments regarding compat referring to supporting browsers with legacy content, and not compat issues with new content and legacy browsers?

@dvoytenko
Copy link

@yoavweiss Yes, the backward compatibility support is the biggest issue I see with this approach as well.

@fantasai
Copy link

@ojanvafai

The aspect ratio calculated from the width and height HTML attributes won't have any effect unless the author has explicitly set at least one of the width or height CSS properties to auto.

Can you explain this more? Why does it require the author to explicitly css the width/height CSS properties to auto to hit the issue?

Because the width and height HTML attribute values are mapped into CSS width and height CSS declarations at the preshint level. See the last paragraph of https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images

Furthermore if that situation happens to be a Web-compat problem, we can change the priority so that the image's own aspect ratio wins over the declared one once it is loaded.

How would this work? It sounds like you're saying the aspect-ratio CSS property would not do anything to elements that have an intrinsic aspect ratio once loaded?

There are use cases for aspect-ratio overriding the intrinsic aspect ratio of replaced elements, so probably by default it should do that. But we could add syntax for deferring to the intrinsic aspect ratio if the image is loaded and it has one, e.g. aspect-ratio: from-image 3/4, if it is needed for Web-compat.

@yoavweiss

The bits that are not clear to me about this solution is how it would be something deployable assuming that not all browsers out there support the new aspect-ratio scheme.

It would not regress any pages except the ones satisfying both conditions in #16 (comment) so unless you think that's a significant Web-compat problem, then there's no reason it can't be deployed. And that Web-compat problem has a solution as already described.

e.g. looking at https://steady-jellyfish.glitch.me/, it seems like a non-supporting browser (e.g. all of them right now) will display responsive images very differently depending on their set width and height values.

There would be no changes to that page under this proposal.

@fantasai - am I missing something here?

Maybe? I'm not understanding your concerns.

Or were your comments regarding compat referring to supporting browsers with legacy content, and not compat issues with new content and legacy browsers?

With legacy content. I don't think there's an issue with new content vs legacy content, either. Again the only cases where they would render differently are images that satisfy both conditions a) and b) in #16 (comment) And again, if this is really a problem we can address it. I would hope that new pages are authored with correct values for their width/height attributes, though.

@bkardell

One thing that I was asking several people about is that it seems clear that there is a rasterizing step here and a change of the reported .naturalHeight and .naturalWidth that is unique to this proposal.

There is no proposal here to change the reported .naturalHeight and .naturalWidth. If they should match the width/height attributes or not, that's a separate issue.

Again for everyone who seems to be confused: there is no proposal to change existing mappings of width/height HTML attributes to CSS width/height properties as defined right now in HTML. There is only an additional mapping of width/height to an aspect ratio so that a replaced element can have an aspect ratio factored into the layout algorithms before it is loaded.

@yoavweiss
Copy link
Collaborator

yoavweiss commented Jun 11, 2019

@yoavweiss

The bits that are not clear to me about this solution is how it would be something deployable assuming that not all browsers out there support the new aspect-ratio scheme.

It would not regress any pages except the ones satisfying both conditions in #16 (comment) so unless you think that's a significant Web-compat problem, then there's no reason it can't be deployed. And that Web-compat problem has a solution as already described.

e.g. looking at https://steady-jellyfish.glitch.me/, it seems like a non-supporting browser (e.g. all of them right now) will display responsive images very differently depending on their set width and height values.

There would be no changes to that page under this proposal.

What that test page is showing is that including width and height attributes with current "typical" responsive image layout would impact the way that images are shown.

How would you advise developers to build new pages that work for the new scheme (but under which, the image's layout dimensions are known at initial layout time), as well as for legacy browsers (even if there, we won't get the "no reflow" benefits of the proposal)?

Can you come up with an example of a responsive image layout where width and height are defined, but the choice of those values has no impact on the eventual responsive image layout in today's browsers?

@fantasai
Copy link

fantasai commented Jun 11, 2019

@yoavweiss

How would you advise developers to build new pages that work for the new scheme (but under which, the image's layout dimensions are known at initial layout time), as well as for legacy browsers (even if there, we won't get the "no reflow" benefits of the proposal)?

The same way many already do now: including width and height attributes that are not inconsistent with the image's own aspect ratio in the HTML, and in the CSS, setting width or max-width to a responsive value and height to auto. (The test page you're showing, btw, doesn't include height: auto, so the first two images, which have height attributes set, get skewed at narrow screen sizes. If you were thinking those examples would be responsive now... they're not. They're currently broken anyway.)

Can you come up with an example of a responsive image layout where width and height are defined, but the choice of those values has no impact on the eventual responsive image layout in today's browsers?

Yes. Setting width: 100%; height: auto creates a responsive image layout and also overwrites the HTML attribute values set in the preshint mapping, so their original values are not used in the final layout.

@jensimmons
Copy link
Author

jensimmons commented Jun 11, 2019

There seems to be a lot of confusion.

There are three combinations of code — and all of them will get the exact same layout result after adding img { aspect-ratio: attr(width) / attr(height); } to the browser as they do today.

  1. Today’s common RWD pattern:
<img src='url.jpg'>
img { width: 100%; }

This code won’t be affected by the proposed change at all, because without height and width attributes, aspect-ratio: attr(width) / attr(height); doesn’t do anything.

  1. Future Best Practice (that's also used today):
<img src='url.jpg' width='400' height='300'>
img { width: 100%; height: auto;}

By adding aspect-ratio: attr(width) / attr(height); to browsers, we’ll get a performance gain when using the width and height attributes.

Yes, Authors will need to be sure to include height: auto to the CSS in order to prevent the height being fixed at 300px, while the width is 100% of the containing block, squishing the image. It’s a simple enough habit to start.

Browsers that implement the proposed code will get a performance gain. Older browsers will not have the performance gain. All browsers will render the layout exactly the same.

  1. A Bad Idea Now. A Bad Idea in the Future.
<img src='url.jpg' width='400' height='300'>
img { width: 100%; }

In a future where we add aspect-ratio: attr(width) / attr(height); to the browser engine, this code will cause images to loose their aspect ratio and be squished. But that’s not because of any proposed change. This is already what happens today.

Our proposal does not change this behavior.

@jensimmons
Copy link
Author

In the past, we thought of width and height as commands for layout. "Make this 400 pixels wide and 300 pixels tall." In the new reality that @fantasai and I are proposing, think instead of these attributes as information about the image file. "Hey browser, you are about to load an image. Here's some information about it — it's 400 pixels wide and 300 pixels tall."

So what happens if I lie, as the Author? How is aspect-ratio: attr(width) / attr(height); affected?

What if I tell the browser the file is 800x600, when really it's 400x300? Well, nothing. Because the math works out. The aspect ratio is still 1.333:1. Everything about how this situation is handled is outside the scope of the proposed change.

What if I tell the browser the file is 300x300, when it's really 400x300? Well, then the aspect ratio gets calculated as 1:1, when the image's actual aspect ratio is not that. But that's exactly what was going to happen with <img src='url.jpg' width='300' height='300'> anyway. It's not what would have happened if we'd not included any height or width information at all — but that's different code. <img src='url.jpg' width='300' height='300'> will not have the same result as <img src='url.jpg' > when the image is a 400x300 image — now or with this proposed change.

This is a very tiny change. It's grabbing the width and height attributes to use in layout calculations before the image downloads, and passing that information along via an idea that can be expressed as aspect-ratio: attr(width) / attr(height);. This is not a fundamental change to the layout algorithm.

@cathiechen
Copy link

cathiechen commented Jun 11, 2019

If we need position a 400x300 image inside a 800px <div> with width: 100%, so I could get the layout size (800x600).

How could we make it by aspect-ratio: attr(width) / attr(height)?

<div style="width: 800px">
  <img src='url.png' width='400' height='300' style='width: 100%;'>
</div>

I guess the layout size of <img> is 800x300. But we want 800x600.

@fantasai
Copy link

@cathiechen Your example code is # 3 in Jen's comment above. As she says, it is broken now and in the future. If you want it to work, you need pattern # 1 or # 2, which will work now and in the future.

@jensimmons
Copy link
Author

jensimmons commented Jun 11, 2019

@cathiechen

Layout would be calculated in the future (with this proposed change) exactly the same way it is calculated today.

<div style="width: 800px">
  <img src='url.png' width='400' height='300' style='width: 100%;'>
</div>

You get an image that's stretched to be 100% of 800px — so 800 px wide. And yes, 300px tall. Because that's what you've coded. That happens today. That would still happen in the future, under this proposed performance enhancement. It would just happen slightly faster.

If you want the image to be aspect-ratio constrained, then you need to use code that will do that. For example:

<div style="width: 800px">
  <img src='url.png' width='400' height='300' style='width: 100%; height:auto;'>
</div>

This layout will work today in exactly the same manner as it will with this performance enhancement. It'll just happen a tiny tiny bit faster with a performance improvement.

aspect-ratio is a CSS property that we are currently defining in the Sizing 4 spec. Once that ships, if you wanted, you could instead write:

<div style="width: 800px; aspect-ratio: 4 / 3;">
  <img src='url.png' width='400' height='300' style='width: 100%; height: 100%;'>
</div>

or all sorts of other things.... there are many ways too accomplish the layout you desire. aspect-ratio would add a tool to our toolkit.

But this issue is not about the aspect-ratio property, or how it works. That is being debated by the CSSWG as part of the Sizing 4 spec.

This issue is about using a tweak to the browser's rendering engine to make width and height matter again, giving us the performance gain we once had by using them before we started applying img { width:100% } to everything. And meanwhile not creating intrinsicsize attributes, because they won't be needed anymore. We can do it in a more elegant way.

What we are discussing affects the performance of layout. It does not affect the results of layout.

@emilio
Copy link

emilio commented Oct 3, 2019

@emilio - I feel like we could have defined at "update the image data" that the height/width attribute values that HTMLImageElement goes with are passed along with the selected source. Do you predict any issues with a solution along those lines?

To be clear, if the attributes are in <img> it should already work, I don't think any spec change is needed. But that constrains you to have all sources with the same aspect-ratio (which is most of the use cases, afaict).

What it does not handle is having multiple sources with different aspect-ratios depending on the viewport size or what not, which is the comment above. As @annevk mentioned that probably needs attributes in <source> and figure out how that should work in the various edge cases.

@sami616
Copy link

sami616 commented Oct 3, 2019

So showing a 16:9 on landscape screens and a 1:1 on portrait screens wouldn't work. Would it work if you dynamically changed the width and height attrs of the img tag at the right breakpoints in this scenario?

@emilio
Copy link

emilio commented Oct 3, 2019

Yes. As long as the attributes are on the <img> inside the picture it'd work.

@yoavweiss
Copy link
Collaborator

To be clear, if the attributes are in <img> it should already work, I don't think any spec change is needed. But that constrains you to have all sources with the same aspect-ratio (which is most of the use cases, afaict)

Unfortunately, when <picture> is involved, the use case is typically art direction where the different sources are not of the same aspect ratio.

@AndresInSpace
Copy link

AndresInSpace commented Oct 3, 2019

As suggested, I made a new proposal for aspect-ratio in regards to art-direction with multiple sources, each having their own aspect-ratio.
Particularly, In regards to <picture> or <video> as both can utilize multiple <source>

gecko-dev-updater pushed a commit to marco-c/gecko-dev-comments-removed that referenced this issue Oct 4, 2019
…height HTML attributes, a=testonly

Automatic update from web-platform-tests
Compute img aspect ratio from width and height HTML attributes

As per this intent to implement:
https://groups.google.com/a/chromium.org/forum/?fromgroups#!topic/blink-dev/hbhKRuBzZ4o

Spec:
WICG/intrinsicsize-attribute#16

Bug: 979891
Change-Id: I0f9ffa1584fa12a41393ef05daffb7238c97e990
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1790472
Commit-Queue: Christian Biesinger <cbiesingerchromium.org>
Reviewed-by: Emilio Cobos Álvarez <emiliochromium.org>
Auto-Submit: Christian Biesinger <cbiesingerchromium.org>
Cr-Commit-Position: refs/heads/master{#699465}

--

wpt-commits: 86ff86de45a67eccc781b84f50ab261c18aad5cf
wpt-pr: 18945

UltraBlame original commit: e8962724f6cc584847fedccd8c0912b6bd00dab6
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified-and-comments-removed that referenced this issue Oct 4, 2019
…height HTML attributes, a=testonly

Automatic update from web-platform-tests
Compute img aspect ratio from width and height HTML attributes

As per this intent to implement:
https://groups.google.com/a/chromium.org/forum/?fromgroups#!topic/blink-dev/hbhKRuBzZ4o

Spec:
WICG/intrinsicsize-attribute#16

Bug: 979891
Change-Id: I0f9ffa1584fa12a41393ef05daffb7238c97e990
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1790472
Commit-Queue: Christian Biesinger <cbiesingerchromium.org>
Reviewed-by: Emilio Cobos Álvarez <emiliochromium.org>
Auto-Submit: Christian Biesinger <cbiesingerchromium.org>
Cr-Commit-Position: refs/heads/master{#699465}

--

wpt-commits: 86ff86de45a67eccc781b84f50ab261c18aad5cf
wpt-pr: 18945

UltraBlame original commit: e8962724f6cc584847fedccd8c0912b6bd00dab6
gecko-dev-updater pushed a commit to marco-c/gecko-dev-wordified that referenced this issue Oct 5, 2019
…height HTML attributes, a=testonly

Automatic update from web-platform-tests
Compute img aspect ratio from width and height HTML attributes

As per this intent to implement:
https://groups.google.com/a/chromium.org/forum/?fromgroups#!topic/blink-dev/hbhKRuBzZ4o

Spec:
WICG/intrinsicsize-attribute#16

Bug: 979891
Change-Id: I0f9ffa1584fa12a41393ef05daffb7238c97e990
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1790472
Commit-Queue: Christian Biesinger <cbiesingerchromium.org>
Reviewed-by: Emilio Cobos Álvarez <emiliochromium.org>
Auto-Submit: Christian Biesinger <cbiesingerchromium.org>
Cr-Commit-Position: refs/heads/master{#699465}

--

wpt-commits: 86ff86de45a67eccc781b84f50ab261c18aad5cf
wpt-pr: 18945

UltraBlame original commit: e8962724f6cc584847fedccd8c0912b6bd00dab6
apostolos added a commit to LWJGL/lwjgl3-www that referenced this issue Oct 26, 2019
Proposal is no longer active. A more elegant solution has been proposed
and is now being implemented by browsers:

WICG/intrinsicsize-attribute#16
zcorpan pushed a commit to whatwg/html that referenced this issue Nov 6, 2019
For when the current request is not available or it doesn't have an intrinsic ratio (such as some SVG content).

This specifies the proposal in WICG/intrinsicsize-attribute#16, which is implemented in both Firefox and Chromium behind a flag.

Tests: https://github.com/web-platform-tests/wpt/blob/a57ec1432f22ac42e8e219a32e2abd7c0baa5b09/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/img-aspect-ratio.tentative.html.
@jensimmons
Copy link
Author

Thank you everyone who's made this happen. It's an exciting improvement to the web.

I made a video to explain it — https://youtu.be/4-d_SoCHeWE
so we can pass the word, and teach people how to make sure their sites get the benefit of this change.

@sami616
Copy link

sami616 commented Nov 9, 2019

Absolutely, one step closer to a less janky web! 👌👏👏

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests