Skip to content
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

A more elegant and easier to use solution #16

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

Comments

Projects
None yet
@jensimmons
Copy link

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

This comment has been minimized.

Copy link

commented Jun 6, 2019

👍 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

This comment has been minimized.

Copy link

commented Jun 6, 2019

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

I like blogging so I blogged it.

@JoshTumath

This comment has been minimized.

Copy link

commented Jun 6, 2019

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

This comment has been minimized.

Copy link

commented Jun 6, 2019

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

@simevidas

This comment has been minimized.

Copy link

commented Jun 6, 2019

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Jun 7, 2019

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Collaborator

commented Jun 7, 2019

@yoavweiss

This comment has been minimized.

Copy link
Collaborator

commented Jun 7, 2019

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

@chrisg88

This comment has been minimized.

Copy link

commented Jun 7, 2019

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

@fantasai

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Member

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.

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

This comment has been minimized.

Copy link
Member

commented Jun 7, 2019

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Jun 10, 2019

Big fan of this fantastic idea!

@bkardell

This comment has been minimized.

Copy link

commented Jun 10, 2019

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

This comment has been minimized.

Copy link

commented Jun 10, 2019

@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

This comment has been minimized.

Copy link
Collaborator

commented Jun 10, 2019

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

This comment has been minimized.

Copy link

commented Jun 10, 2019

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

@fantasai

This comment has been minimized.

Copy link

commented Jun 11, 2019

@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

This comment has been minimized.

Copy link
Collaborator

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link
Author

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

This comment has been minimized.

Copy link
Author

commented Jun 11, 2019

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

This comment has been minimized.

Copy link

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

This comment has been minimized.

Copy link

commented Jun 11, 2019

@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

This comment has been minimized.

Copy link
Author

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.

@jensimmons

This comment has been minimized.

Copy link
Author

commented Jun 11, 2019

Just to be clear, the idea under discussion is the idea that browsers could add aspect-ratio: attr(width) / attr(height) deep inside their internals, and use the width and height attributes to calculate layout before an image has dowloaded, even when width: 100%; or other such CSS is applied.

Honestly, browser makers could have done this nine years ago, when RWD got started. It doesn't actually require an aspect-ratio property in CSS. The more I look at it, and the more I talk to browser engineers, the more I wonder why this didn't happen years ago. Seems like something that just slipped through the cracks.

If, dear reader, you are intrigued by the idea of an aspect-ratio property in CSS — yay! Please leave this issue, and go read https://drafts.csswg.org/css-sizing-4/#ratios. Then comment in the appropriate channels for discussing that spec. Let's keep the discussion here to whether or not we think we can replace the need for new intrinsicsize attributes with the good old fashion width and height — plus this performance change in what the browser does with those attributes.

If we can think of usecases that aren't covered, or a true webcompat problem, then we should discuss those.

@cathiechen

This comment has been minimized.

Copy link

commented Jun 11, 2019

@fantasai @jensimmons Thanks for the explanation.

So I could make it by:

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

And I have to add 'height:auto;', it seems make width/height more complex than before.

However, intrinsicsize seems easier:

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

Sorry, I didn't explain why I personally feel this way.

First, the usage seems not consistent with aspect-ratio.
For aspect-ratio, we could compute height by setting "width: 100%; aspect-ratio: 4 / 3;". While we need to set both CSS width and height in this proposal. The extra "height: auto" seems is learning price too.

Second, setting both attr and CSS width/height is treated as duplicated before. And now we encourage to do it.

@jensimmons

This comment has been minimized.

Copy link
Author

commented Jun 11, 2019

Layout belongs in CSS. Not HTML.

@bkardell

This comment has been minimized.

Copy link

commented Jun 11, 2019

After some discussion with @fantasai to figure out how to clarify my point above, let me offer this clarification to my above post:

It seems hard to compare the equivalence of these proposals on at least one point: As currently written in the readme, the intrinsic size attribute proposal specifies a side effect of rasterizing at this size and affecting the reported .naturalWidth and .naturalHeight attributes. There are open issues discussing the importance of this (for example #11) but It feels like it would be very helpful to determine if this is an important distinction for purposes here? I think it's fine to resolve that elsewhere, I just wanted to note in case it isn't obvious that this seems like a distinction, currently.

@yoavweiss

This comment has been minimized.

Copy link
Collaborator

commented Jun 13, 2019

  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.

@jensimmons - Thanks for outlining option 2. That is the piece I was missing.

@yoavweiss

This comment has been minimized.

Copy link
Collaborator

commented Jun 13, 2019

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

@jensimmons @fantasai - could you outline potential scenarios where implementing this would change layout in existing sites? (assuming no one is currently using aspect-ratio)

@jensimmons

This comment has been minimized.

Copy link
Author

commented Jun 16, 2019

could you outline potential scenarios where implementing this would change layout in existing sites? (assuming no one is currently using aspect-ratio)

No Authors are using aspect-ratio because it doesn't exist in any browser yet. It's being proposed in CSS Sizing 4.

The one situation where there might result in a change to layout was described by @fantasai above:

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.

So let's take the example from my comments above and dig deeper. To make things extra clear, let's look at several combinations, including those that don't have any affect on the results of layout.

EXAMPLE 1:

First, a situation where there is not a mismatch between the stated size and the real size. We have a 400x300 px image, and we state in the attributes: width='400' height='300'.

There are four parts of code/data:

<div><img src='url.jpg' width='400' height='300'></div>
img { aspect-ratio: attr(width) / attr(height); }
img { width: 100%; height: auto; } div {width: 800px; }
an image file that is 400px by 300px

So what happens?

The HTML loads. The browser grabs width='400' height='300' from the HTML and calculates aspect-ratio: 400 / 300. (This part is new, today's browsers do not do this).

The browser starts calculating layout, and makes a box for the image. It expects width='400' height='300' — but then also sees img { width: 100%; height: auto; }. So it calculates the size of the containing block — 800px wide. Then it makes a block for the image that is 100% of 800px, so, 800px wide. It sees the height should be auto... and then...

Today, the only way a browser can calculate this auto height is by having the data that's in the image file, so it has to finish downloading the image before it can figure out the final height.

With the proposed new solution, it will take aspect-ratio: 400 / 300, apply that to the 800px-wide box, and figure out that the box should be 600px in height, (800 ÷ 1.3333333 = 600). This calculation will likely happen before the image is downloaded, saving a repaint and the jank it could cause. Once the image has loaded, it fits nicely into the 4:3, 800 x 600 box. This is what we are trying to do — make things faster and less janky. 👍 🥇

EXAMPLE 2:

Let's now imagine what happens if there is a mismatch between the stated size of the image, and the real size of the image.

img { aspect-ratio: attr(width) / attr(height) }
<div><img src='url.jpg' **width='300'** height='300'></div>
img { width: 100%; height: auto; } div {width: 800px; }
an image file that is 400px by 300px

(This is the same code as above, except with width='300'.)

  1. The HTML loads. The browser grabs width='300' height='300' and calculates aspect-ratio: 300 / 300
  2. The browser starts calculating layout, and makes a box to hold the image. It expects width='300' height='300' — but then also sees img { width: 100%; height: auto; }. It calculates the size of the containing block — 800px wide. So, it makes a block for the image block that's 100% of 800px = 800px wide.
  3. To calculate the height of the box, it takes 800px-wide, and aspect-ratio: 300 / 300 (which is the same as aspect-ratio: 1 / 1, a square), and makes a box that is 800px wide. (800 ÷ 1 = 800),
  4. Then the image loads. It's not a square. But it's being displayed as a square. The image is squished.

EXAMPLE 3:

Now if this were 2005 (aka, before responsive web design), and we were not applying img { width: 100%;} we would get this exact same result. If you have:

<img src='url.jpg' **width='300'** height='300'>
an image file that is 400px by 300px

You get an image that is morphed by the HTML attributes. So any old websites will be fine (any website not applying a percent width to images/video via width, min-width, or max-width). If the Authors intended to reshape the aspect ratio of the image by using HTML attributes that don't match, that's what they got when they coded the website, that's what they'll get now.

EXAMPLE 4:

The one different in layout — perhaps (depending on the details of how we implement this proposal) — would come when we are using RWD with img { width: 100%; height: auto; } (or anything similar):

<div><img src='url.jpg' **width='300'** height='300'></div>
img { width: 100%; height: auto; } div {width: 800px; }
an image file that is 400px by 300px

Currently this is what this example does — without img { aspect-ratio: attr(width) / attr(height) }:

  1. The HTML loads. The browser grabs width='300' height='300'.
  2. The browser starts calculating layout, and makes a box to hold the image. It expects width='300' height='300' — but then also sees img { width: 100%; height: auto; }. It calculates the size of the containing block — 800px wide. So, it makes a block for the image block that's 100% of 800px = 800px wide.
  3. To calculate the height of the box, it waits for the image to download. It sees that the image is 400x300, with an intrinsic aspect ratio of 4:3. So it calculates a height of 600px.
  4. The image is not squished. It's displayed in a 800x600px box.

This is the one potentially different layout result.

If you compare Example 2 with Example 4, you see the different. The two examples are the same code & file... one with img { aspect-ratio: attr(width) / attr(height) } and one without.

Before this proposed change, the image is displayed at 800x600. After, it could potentially be displayed at 800x800.

This only happens if all four of the following conditions are met:

  1. The image's intrinsic aspect ratio (the real aspect ratio once you've download the file), and the aspect ratio that would be calculated from the width & height attributes do not match.
  2. img { width: 100%; height: auto; } has been applied
  3. We write the CSS specification so that browsers prioritize the calculated aspect ratio over the image's aspect ratio. We don't have to do it this way, as @fantasai stated:

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.

It sort of makes sense to let the CSS calculation win, but if that creates a true web compatibility problem, then we could easily get the browsers to enforce the image's aspect ratio instead, once the image has downloaded. Perhaps we'd need a toggle... this is where some research and conversations need to continue in the CSSWG about the Sizing 4 specification, and these details.

@chrishtr

This comment has been minimized.

Copy link

commented Jun 18, 2019

I think what is being proposed in the original statement of this issue makes a lot of sense, and can be implemented simply, safely and easily, with one small tweak: after the image is loaded its actual intrinsic size takes precedence over the width and height attributes.

Also, FTR this tweak was mentioned [earlier in the conversation by @fantasai].(#16 (comment))

The solution is quite simple and nice, and requires no new CSS attributes for aspect-ratio or anything. As mentioned here, the user-agent style sheet of aspect-ratio: attr(width) / attr(height) need only be conceptual at this time, and the actual implementation is with explicit C++ code in the rendering engine.

I discussed it offline with @ojanvafai and @yoavweiss and I think everyone seems cool with it as an incremental step to avoid extra intermediate layouts.

(@jensimmons @fantasai I know we discussed this back in Feb at the CSSWG F2F, and I said I would follow up. Sorry for the delay.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.