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

[css-sizing] Removing intrinsic aspect-ratio from an image #6257

Open
mirisuzanne opened this issue May 1, 2021 · 15 comments
Open

[css-sizing] Removing intrinsic aspect-ratio from an image #6257

mirisuzanne opened this issue May 1, 2021 · 15 comments

Comments

@mirisuzanne
Copy link
Contributor

The current specification for aspect-ratio allows explicit ratios, or the "natural" aspect ratio from a replaced element. But there is not currently any explicit way to remove the natural aspect ratio from replaced elements.

In grid & flexbox context, it is often useful to remove the natural ratio of an image, apply object-* properties, and allow the images to stretch in whatever space is available or defined by the grid-template. Currently, I'm not sure there's a way to do it without adding a wrapper, and using absolute position.

It seems like we should be able to do this with something like aspect-ratio: none?

@tabatkins
Copy link
Member

That's pretty reasonable, yeah. none definitely makes sense as the value for it.

@bfgeek
Copy link

bfgeek commented May 26, 2021

We already have a mechanism to do this with contain: size which will make replaced elements have no aspect-ratio, and a 0x0 natural size. The issue with aspect-ratio: none is that it wouldn't necessarily clear out intrinsic-size which might not be what people want.

@aethanyc
Copy link

aethanyc commented May 26, 2021

The contain:size and aspect-ratio interaction was discussed in #5550

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-sizing] Removing intrinsic aspect-ratio from an image.

The full IRC log of that discussion <dael> Topic: [css-sizing] Removing intrinsic aspect-ratio from an image
<dael> github: https://github.com//issues/6257
<dael> TabAtkins: If miriam isn't on I can take it
<dael> miriam: I was playing with images in a grid. Wanted to be able to remove a-r and use object:position and fit to have it fit without contributing to grid sizing. I thought a-r:none would be a way to do that
<dael> TabAtkins: Makes sense
<dael> iank_: Made a comment on GH just now. contain:size does it todya. a-r:none might not be best b/c won't clear out natural size of image. Could fallback to 300x150 which might still contribute. Want to be cognizant of that
<dael> Rossen_: Is that behavior of sizing today which is based on actual size and that's how you infer the a-r?
<dael> iank_: Yes, it's subtle. image has a-r and natural size. a-r:none would 0 out the a-r. Wouldn't 0 out natural size and that may still contriute to grid area. contain:size does both, null hte a-r and set the natural size to 0.
<dael> iank_: If the use case if we want both we've got contain:size to do that
<dael> Rossen_: Isn't prop only to remove a-r and not the size an image contributes to the grid area if being sized for its contribution to the sizing algo? Question to miriam
<dael> miriam: I think my goal was to remove any size contribution so might be more what contain:size does. a-r is what I assume would allow me to remove it
<dael> Rossen_: I think a-r willl only remove 2:1 or whatever it happens to be. Height might be different than expect. 2x1 grid where first cell is image and that image contributes a width. Auto height and not natural intrinisic height.
<dael> Rossen_: Let's say image has 100w x 50h. a-r by sizing algo computes as 2:1. We can say this is ignored but then your height can be changed by sizing algo based on second cell.
<dael> Rossen_: Subtle difference. not discounting that a-r:none will still be effective and useful. Certainly what you're looking for is contain:size to not have any contribution
<dael> miriam: Okay
<dael> Rossen_: I guess issue boils down to do we have enough use cases to justify a-r:none by itself
<TabAtkins> Actually now I'm confused as to what 'aspect-ratio: 1/1' does to the natural sizes of an image with 300x150 size :/
<dael> Rossen_: I see TYLin linked another issue discussing this which was closed
<dael> emilio: Another tricky thing. Object:fit doensn't interact well with containment
<dael> miriam: Seeing that in my demo. Trying to add contain:size
<dael> [everyone silently experiments]
<dael> Rossen_: Back to the proposal. a-r:none the way you described the anticipated behavior is more than a-r:none. I think we agree on that for this use case
<dael> Rossen_: First quesiton is what is the best wya to achieve intended behavior. Second question is does a-r:none make sense in other use cases. If we need more time we can revisit next week
<dael> miriam: Works for me
<dael> Rossen_: Any other comments? I think we've captured enough feedback and lines of thought
<dael> Rossen_: if there's findings to have a-r:none we can bring it back

@tabatkins
Copy link
Member

@bfgeek Your question led me to suddenly realize I'm not sure what would happen to the natural sizes of a 300x150 image with aspect-ratio: 1/1, let alone none.

@Loirooriol
Copy link
Contributor

Loirooriol commented May 26, 2021

Since object-fit doesn't seem to work well with contain: size, another approach can be:

width: 0;
height: 0;
min-width: 100%;
min-height: 100%;

This should avoid natural sizes, 300x150 default intrinsic size, etc.

@bfgeek
Copy link

bfgeek commented May 26, 2021

Looking at the current behaviour of object-fit with contain: size makes me pretty convinced that it's broken today.

@bfgeek
Copy link

bfgeek commented May 26, 2021

Specifically - object-fit algorithm is using the "natural size" which contain: size is zeroing out. A potential improvement would be for contain: size to have an affect on the "natural size" for layout purposes only.

@tabatkins
Copy link
Member

Yeah, that interaction does seem to be implied by the spec today, so good on impls for following the spec, but I agree it's a broken behavior and we should change it, probably in exactly the way you suggest.

@Loirooriol
Copy link
Contributor

It's true that https://drafts.csswg.org/css-contain/#sizing-as-if-empty says

Replaced elements must be treated as having an natural width and height of 0 and no natural aspect ratio.

But this is just for the purpose of sizing the <img> element or whatever. https://drafts.csswg.org/css-contain/#laying-out-in-place says

The containment box's content (including any pseudo-elements) must then be laid out into the now fixed-size containment box normally.

So to me it doesn't seem like implementations are following that?

@jensimmons
Copy link
Contributor

I won't be able to attend the 7pm CSSWG call today — it's too late in the day for me to have the energy. But this seems cool.

To better understand what's currently possible, I wrote this demo: https://codepen.io/jensimmons/pen/3c9e5163fb70b7fb25adad0db97494fa?editors=1100
Aspect ratios (natural or set as preferred) only works if one of the dimensions is auto, so an alternative solution in some usecases is to set both width and height to something besides auto, like 100%.

Even if other piles of code can reach the same result, aspect-ratio: none; is a easily understandable straightforward solution. And elegance is good.

I'd love to see what @mirisuzanne was coding up.

I wouldn't want this to only work for images / <img>, but instead for any & all elements that have a natural aspect ratio — including <video>.

@Loirooriol
Copy link
Contributor

@jensimmons Note, though, that only works because the row has a fixed height. If you change grid-template-rows: 50vh 50vh into

grid-template-rows: 1fr 1fr;
height: 100vh;

then the image will be too tall in latest Chromium. Because the 1st column will be 100vw - 600px, then the image will be horizontally stretched to fill that space, and then the aspect-ratio will make the intrinsic row grow too much.

Sure, you have height: 100%, but when sizing the rows, the percentage is indefinite, so it behaves as auto.

A more general solution, as I posted in #6257 (comment), is

img {
  width: 0;
  height: 0;
  min-width: 100%;
  min-height: 100%;
}

This way the intrinsic contribution is 0, but when sizing for real, it will fill the desired space.

@bfgeek
Copy link

bfgeek commented Jun 9, 2021

Specifically for the aspect-ratio: none case consider the following example:

<!DOCTYPE html>
<div style="display: inline-grid; border: solid;">
  <svg style="background: green;"></svg>
</div>

https://www.software.hixie.ch/utilities/js/live-dom-viewer/?saved=9397
(FF seems to have a bug with above).

Here the <svg> element has no aspect-ratio (set the width/height at the other dimension will stay the same size).
This is how:

<!DOCTYPE html>
<div style="display: inline-grid; border: solid;">
  <img src=image style="aspect-ratio: none;"></svg>
</div>

.... would behave.

The element would still take up space by default - using its natural-size, but have no aspect-ratio. This might be desired! But isn't exactly what the use case is describing unless I'm mis-understanding.

@astearns astearns removed the Agenda+ label Jun 9, 2021
@mirisuzanne
Copy link
Contributor Author

My goal was to remove the aspect-ratio of the image for the purpose of sizing/layout, but still have the natural ratio available when using object-fit. It sounds to me like that specific case should work simply with contain:size, and could be filed as an implementation bug? Once that's fixed, the syntax is straight forward:

img {
  contain: size;
  object-fit: cover;
}

Ian's distinction here makes sense to me. Even though my first instinct was to remove the aspect-ratio of the image, I am actually attempting to remove its size contribution - while keeping the natural aspect ratio intact. As far as I'm concerned, this can be filed as a bug, and closed as no-change.

@mirisuzanne
Copy link
Contributor Author

Not sure if there's a change required in the contain spec for this? I imagine we'd also need WPT tests and browser bugs. If none of that has happened yet, I can help push on it. I think this would be a very useful update.

eeeps added a commit to eeeps/wpt that referenced this issue Apr 3, 2024
[css-images] [css-contain]

`object-fit` should use the "real" natural aspect ratio, and `contain: size` should not ruin this

w3c/csswg-drafts#10116
w3c/csswg-drafts#6257
eeeps added a commit to eeeps/wpt that referenced this issue Apr 4, 2024
[css-images] [css-contain]

`object-fit` should use the "real" natural aspect ratio, and `contain: size` should not ruin this

w3c/csswg-drafts#10116
w3c/csswg-drafts#6257
eeeps added a commit to eeeps/wpt that referenced this issue Apr 4, 2024
[css-images] [css-contain]

`object-fit` should use the "real" natural aspect ratio, and `contain: size` should not ruin this

w3c/csswg-drafts#10116
w3c/csswg-drafts#6257
tcaptan-cr pushed a commit to web-platform-tests/wpt that referenced this issue Apr 10, 2024
* Test interaction between object-fit and contain:size

[css-images] [css-contain]

`object-fit` should use the "real" natural aspect ratio, and `contain: size` should not ruin this

w3c/csswg-drafts#10116
w3c/csswg-drafts#6257

* Change image-rendering: crisp-edges to pixelated

Chromium doesn’t support `crisp-edges`

* Remove whitespace to make linter happy
moz-v2v-gh pushed a commit to mozilla/gecko-dev that referenced this issue Apr 19, 2024
…d `contain: size`, a=testonly

Automatic update from web-platform-tests
Test interaction between `object-fit` and `contain: size` (#45563)

* Test interaction between object-fit and contain:size

[css-images] [css-contain]

`object-fit` should use the "real" natural aspect ratio, and `contain: size` should not ruin this

w3c/csswg-drafts#10116
w3c/csswg-drafts#6257

* Change image-rendering: crisp-edges to pixelated

Chromium doesn’t support `crisp-edges`

* Remove whitespace to make linter happy
--

wpt-commits: ae05e1ac2530c57f3e6205c50d6176b4875098ff
wpt-pr: 45563
ErichDonGubler pushed a commit to erichdongubler-mozilla/firefox that referenced this issue Apr 22, 2024
…d `contain: size`, a=testonly

Automatic update from web-platform-tests
Test interaction between `object-fit` and `contain: size` (#45563)

* Test interaction between object-fit and contain:size

[css-images] [css-contain]

`object-fit` should use the "real" natural aspect ratio, and `contain: size` should not ruin this

w3c/csswg-drafts#10116
w3c/csswg-drafts#6257

* Change image-rendering: crisp-edges to pixelated

Chromium doesn’t support `crisp-edges`

* Remove whitespace to make linter happy
--

wpt-commits: ae05e1ac2530c57f3e6205c50d6176b4875098ff
wpt-pr: 45563
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants