w3c / csswg-drafts

CSS Working Group Editor Drafts
https://drafts.csswg.org/
Other
4.5k stars 661 forks source link

[css-grid][css-sizing] Aspect Ratio #333

Open fantasai opened 8 years ago

fantasai commented 8 years ago

Grid & Flexbox make the aspect ratio problem more urgent, since they're so much better at flexible sizing than previous layout models...

Jen Simmons wrote:

I wish big time there were a way to transfer a calculated size from one dimension to the other. AKA… I define columns to be 1fr each. And I want the cells to be squares (or always have a 16x9 ratio, or whatever — but to maintain a fixed aspect ratio). How can I define the rows to be 1fr-from-the-column-calculation?? I want that.

fantasai commented 8 years ago

Filing also under Grid, because it needs to be handled in a way that also works with grid-template-rows/cols.

fantasai commented 6 years ago

https://lists.w3.org/Archives/Public/www-style/2018Jan/0023.html is a related problem; we could solve it if HTML calculates an aspect-ratio value to inject at the preshint level alongside width/height. We should file a follow-up issue with HTML once we've addressed this issue in CSS.

ewanm89 commented 6 years ago

How about a simple ew relative unit added that is percentage of element width?

Then we can just height: 100ew; to make something square or height: 56.25ew for a 16:9 box?

Obviously with an addendum that ew is ignored on the width property. This way, it can apply to all elements as they already work?

tobireif commented 6 years ago

This feature really is needed. It's a common use case to have to ensure a certain aspect ratio for each item, eg in Flexbox or Grid, through all viewport widths / element widths.

There are many results for just one hack https://www.google.com/search?q=flexbox+aspect+ratio+padding-top+100%25 and eg https://css-tricks.com/aspect-ratio-boxes/

We need a real solution.

@ewanm89 wrote

How about a simple ew relative unit added that is percentage of element width?

Then we can just height: 100ew; to make something square or height: 56.25ew for a 16:9 box?

I think I like it.

tobireif commented 6 years ago

Another aspect ratio ticket: https://github.com/w3c/csswg-drafts/issues/1173

tobireif commented 6 years ago

@fantasai wrote:

Filing also under Grid, because it needs to be handled in a way that also works with grid-template-rows/cols.

The Grid label unfortunately has been removed. I hope it will get added back.

tabatkins commented 6 years ago

We removed the label because it's not a blocker for Grid 2; it's a Sizing issue. We'll want to think about Grid when designing a solution, but in the meantime it's clogging up our view of what needs fixing for Grid. ^_^

ewanm89 commented 6 years ago

While I would agree with the principle, the sizing issue has been something that should have been fixed decades ago. And it is just getting more and more desperate without a fix in sight.

tobireif commented 6 years ago

Having an element width "ew" unit would be so useful ... I already use it via EQCSS. An example from one of my projects:

@element .page {
  img[src$=".svg"] {
    width: 30ew;
  }
}

The nice thing is that if .page has a max-width, the effective ew value will stop growing after that max width. With vw the effective value would continue to grow with the viewport.

And it could be a nice way of specifying aspect ratios (as @ewanm89 wrote earlier), eg height: 100ew in order to get a 1:1 ratio / a square.

jonjohnjohnson commented 6 years ago

width: 30ew;

This specific example of ew unit confuses me. Are you setting the img to 30% of the width of the .page element? So the img ew unit comes from the parents width? Or are you somehow wanting to set the width of the img to 30% of what the width of the img would compute to if left unset?

Regardless, I'd be more interested in a property or method (https://github.com/w3c/csswg-drafts/issues/820#issuecomment-268282394) that comes with constraints on display and box, cleanly interacting with min/max-height/width and values like min/max-content/min()/max()/etc... something to more cleanly accomplish this... http://jsbin.com/yuvaka/9/edit?html,output

tobireif commented 6 years ago

This specific example of ew unit confuses me.

It's code from an actual project, and it works 😀

The more typical element query would look like this, for example:

@element .page and (max-width: 422px) {
  /* Inside this block, the element-width unit "ew" is based on the .page element. */
}

Are you setting the img to 30% of the width of the .page element?

Yep, that's what this EQCSS-powered code does.

So the img ew unit comes from the parents width?

It comes from the .page element, which could be the parent of the image element, but it could also be a far higher ancestor for example.

The docs are at https://elementqueries.com/ -> "ew (element width)" "EW Units", and (with more info) at https://tomhodgins.github.io/element-queries-spec/element-queries.html#ew .

Some more instances of "ew" units in use: https://tobireif.com/demos/grid/view_demo_source/ -> search-in-page for all "ew;" . (The demo itself is at https://tobireif.com/demos/grid/ .)

Regardless, I'd be more interested in a property or method [aspect-ratio specific]

Having a property (or set of properties) specifically for aspect-ratio would be great!

The "ew" unit is a fundamental part of element queries / container queries, and it could also be used for ensuring any aspect ratio:

@element #foo {
  #foo {
    height: 100ew;
  }
}

... but having one or more properties specifically for aspect-ratio would be even better (and I hope we'll get native element queries including element-width units in any case).

Dan503 commented 6 years ago

Are you setting the img to 30% of the width of the .page element?

Yep, that's what this EQCSS-powered code does.

That wouldn't be how an ew unit works in real CSS though.

I think if ew was used on the width property it would equate to the same as if you used %.

I'm glad the grid tag was removed. This is a unit that should be usable anywhere like the vw unit, not just on grid items.

Imagine how great it would be to be able to write font-size: 20ew,. Now you can have text that scales with the size of its container rather than the size of the viewport! (font-size: 20vw;)

tobireif commented 6 years ago

That wouldn't be how an ew unit works in real CSS though.

It could be spec'd to work just as in EQCSS.

I think if ew was used on the width property it would equate to the same as if you used %.

@element .select-any-element-here-not-necessarily-the-parent and (max-width: 422px) {
  /*
  Inside this block, the element-width unit "ew" is based on the selected element.
  It can be any element.
  */
}

This is a later example from above:

@element #foo {
  #foo {
    height: 100ew;
  }
}

This is a unit that should be usable anywhere like the vw unit, not just on grid items.

Yes, sure!

Perhaps you want to open a new ticket for the ew unit? (there's isn't one yet)

Imagine how great it would be to be able to write font-size: 20ew,. Now you can have text that scales with the size of its container rather than the size of the viewport! (font-size: 20vw;)

In https://tobireif.com/demos/grid/ https://tobireif.com/demos/grid/view_demo_source/ there is for example font-size: 57ew;.

But even better for that type of use case would be to be able to say "always fit this line of text in this container (by adjusting property foo eg font-size or letter-spacing), no matter what font is used".

Related: https://github.com/w3c/csswg-drafts/issues/2528

SebastianZ commented 6 years ago

This is a later example from above:

@element #foo {
  #foo {
    height: 100ew;
  }
}

This is a unit that should be usable anywhere like the vw unit, not just on grid items.

Yes, sure!

Perhaps you want to open a new ticket for the ew unit? (there's isn't one yet)

Why open a new issue? This issue is about adding a way to define an aspect ratio. And the ew unit is one possible solution for it, so it belongs in here.

What should be discussed separately is the @element rule defining the element things like the ew unit relate to.

Sebastian

tobireif commented 6 years ago

Why open a new issue?

Because it's a potentially separate feature, and has many, many use cases beyond being one potential option for ensuring aspect ratios.

This issue is about adding a way to define an aspect ratio. And the ew unit is one possible solution for it, so it belongs in here.

Yes it sure can be discussed here! ... as far as it pertains to the use case of specifying aspect ratios.

And the ew unit has many other use cases so it would sure be sensible to open a separate ticket in addition to that.

This aspect ratio ticket here might well get closed as soon as there's a solution which doesn't involve or require "ew" units - then there'd be no ticket for all the use cases that the ew unit solves (eg specifying font-size based on an some element's with).

What should be discussed separately is the @element rule defining the element things like the ew unit relate to.

You wrote that the ew unit is one possible solution for it, so it belongs in here. All parts and aspects of one possible aspect ratio solution eg

@element #foo {
  #foo {
    height: 100ew;
   // eg plus minmax()
  }
}

can be discussed here as long as it specifies an aspect ratio (and people are working on element queries anyways, see https://github.com/tomhodgins/cq-usecases , so there's no need for a new ticket for that).

jensimmons commented 6 years ago

This past week, we wrote a draft at: https://drafts.csswg.org/css-sizing-4/#ratios

tobireif commented 6 years ago

This past week, we wrote a draft at: https://drafts.csswg.org/css-sizing-4/#ratios

From a quick look:

Very cool 👍

Regarding the options: option B "min-height: 1ar" is nicely descriptive, and it requires just one line (as opposed to option A).

jensimmons commented 6 years ago

https://twitter.com/Daniel_Tonon/status/1054337270151569408 brings up the desire to set an aspect ratio on the content box, set margins in one dimensions (say in block direction), and be able to assign margins in the other direction (inline) using from-ratio in order to make a margin box that also keeps to the aspect ratio. Same for padding.... etc.

Dan503 commented 6 years ago

Actually there is one limitation in using from-ratio compared to an ar unit.

ar is pretty much self contained.

from-ratio on the other hand needs the aspect-ratio property to be set which comes with a bunch of its own effects.

If you wanted to add aspect-ratio sizing to padding/border/margin but didn't want the box itself to be sized using aspect-ratio, that would be much more difficult (maybe even impossible) to achieve using from-ratio. It would be easily achievable using an ar unit though.

tomhodgins commented 6 years ago

Glad to see some action on this - I went through the idea of an aspect-ratio property a while ago and specced out what I wanted from a developer's perspective, including when I'd expect width, height, and aspect-ratio to take effect in cases where multiple are declared: https://tomhodgins.github.io/aspect-ratio-spec/aspect-ratio.html

Hope this helps!

jensimmons commented 6 years ago

The WICG has a group that worked on Aspect Ratio for a bit (5 issues): https://github.com/WICG/aspect-ratio.

It also points to this draft: https://jonathankingston.github.io/logical-sizing-properties/#propdef-aspect-ratio

tomhodgins commented 6 years ago

I'm a WICG member the majority of issues in that repository are mine 🤣The dream spec I linked to here grew out of the discussion from that repository but is a little more fleshed out in terms of what the aspect-ratio property should do, when it should apply etc

fantasai commented 6 years ago

The CSS Working Group just discussed Aspect Ratio.

The full IRC log of that discussion <fantasai> Topic: Aspect Ratio
<fantasai> jensimmons: There's been a longstanding desire for aspect ratio support in CSS
<fantasai> jensimmons: Brought up not only because I brought it up, but many people around the worl dhave been writing blog posts talking about this
<fantasai> jensimmons: So fantasai drafted up some spec text last week
<fantasai> jensimmons: Here's an example
<fantasai> jensimmons: People are resizing their images in CSS, and width is being set to 100% and height to auto, and the image keeps its aspect ratio
<fantasai> jensimmons: But some elements do not have an intrinsic aspect ratio
<fantasai> jensimmons: e.g. iframe, article, tec.
<fantasai> jensimmons: Some are replaced elements, some are not, but they odn't have intinsic aspect ratio so things get squished
<fantasai> jensimmons: Why are people not using the video element?
<fantasai> jensimmons: THey're using youtube, vimeo, etc.
<fantasai> jensimmons: because of adaptive bitrate streaming
<fantasai> jensimmons: but it's a reality that's very important for supporting varyious netowrk connections
<fantasai> jensimmons: so videos in iframes are important
<fantasai> jensimmons: Here's what happens when you try to resize the iframe: no preservation of the aspect ratio
<fantasai> jensimmons: First solutionof the industry was fitvids.js
<fantasai> jensimmons: It's not a great idea
<fantasai> jensimmons: Everything since has been using the padding hack
<fantasai> jensimmons: Using the fact that pading in % is going off the width rather than the hack, and ppl exploiting that to get aspect ratio
<fantasai> jensimmons: Only some ppl know about it, it's tricky to use..
<fantasai> jensimmons: Would be much better to have something in CSS to solve this
<fantasai> jensimmons: Our current thoguht is to use a property, 'aspect-ratio: 16 / 9' e.g.
<fantasai> jensimmons: This would cause the element to hook into all the existing rules that handle elements with an asepct ratio
<fantasai> jensimmons: This is written up as a super rough draft in CSS sizing L4
<astearns> https://drafts.csswg.org/css-sizing-4/#ratios
<fantasai> https://drafts.csswg.org/css-sizing-4/#ratios
<fantasai> jensimmons: Videos would be done like
<fantasai> jensimmons: iframe { aspect-ratio: 16/9; width: 100%; height: auto; }
<fantasai> jensimmons: Syntax of the property is coming from the Media Query syntax for aspect-ratio
<fantasai> jensimmons: Idea was just to copy that syntax
<fantasai> jensimmons: for consistency and also I like that
<fantasai> jensimmons: SO that's great, solve things like video in iframj
<fantasai> jensimmons: But there are also other cases where we care about aspect ratios
<fantasai> jensimmons: Let's say you want a bunch of squares with text in them
<fantasai> jensimmons: In this example I used viewport units, but it would be nice to be able to just give an intrinsic aspect ratio
<fantasai> jensimmons: Here's a use case
<fantasai> jensimmons: We have boxes with different amounts of content in them, and we want them to have 2:1 aspect ratio
<fantasai> jensimmons: Problem here is that in some cases there's too much text, and it oveflows!
<fantasai> jensimmons: Want to be able to say that "I want this aspect ratio as my min-height, if the box get bigger let it grow like usual"
<fantasai> jensimmons: Two options in the raft
<fantasai> jensimmons: Option A is to have a keyword of some kind which you can put in min-height to request from-ratio, and then say that the height is max-content
<fantasai> jensimmons: article { aspect-ratio: 2 / 1; height: max-content; min-height: from-ratio; }
<fantasai> jensimmons: Other possibility is to use 'ar' units, which come from grid L2 spec
<fantasai> jensimmons: I would change the name, don't think 'ar' is the right name
<fantasai> jensimmons: But basically it grabs the number of the corresponding property in the opposite dimension and multiplies it
<fantasai> jensimmons: e.g. we ahve gaps in one side, the other side says 2ar, it'll be twice the width of the other-dimension gap
<fantasai> jensimmons: So we could use those in the height properties, e.g. 'min-height: 0.5ar'
<fantasai> jensimmons: Going further, it'd be great if we could use attr() to grab the width/height attributes from the HTML and put it into the aspect-ratio
<fantasai> jensimmons: This would solve a performance problem everyone wants to solve, to do layout before the image loads
<fantasai> jensimmons: There's been a variety of proposals for adding new attributes to do this, but we could just use it with CSS by using attr
<TabAtkins> https://github.com/ojanvafai/intrinsicsize-attribute for the HTML-based way to set intrinsic sizes/ratio before loading them.
<fantasai> jensimmons: e.g. iframe { aspect-ratio: attr(width px) / attr(height px); }
<TabAtkins> Still an early proposal, could use some feedback from us.
<fantasai> gregwhitworth: I'm excited about this topic
<fantasai> gregwhitworth: Prefer the aspect-ratio syntax from MQ
<TabAtkins> (I've given some feedback, I think it's pretty decent.)
<fantasai> gregwhitworth: We also did talk about aspect ratio in picture elements
<tantek> +1 I'm excited to see aspect ratio solved
<fantasai> gregwhitworth: I think we'd like an HTML solution because we want to do it earlier
<fantasai> gregwhitworth: but of course also in CSS too
<fantasai> gregwhitworth: Interested in the other stuff
<fantasai> gregwhitworth: We have a WICG thread under ? for asect ratio that has additiona issues to think about that we should think about
<TabAtkins> (Ojan's proposal is *just* about setting intrinsic sizes of replaced elements that *already have* aspect-ratio information. Not directly intersecting with the 'aspect-ratio' property.)
<florian> fantasai: in terms of adding attributes to HTML, we were looking at this, and thinking we can just do that using the height and with attribute
<florian> fantasai: currently, they link to the width and height property, so you loose them when you set the css properties
<florian> fantasai: but we could change that, to make them also plug into the aspect-ratio property
<florian> fantasai: so if you set them in css, you'd override the width/height, but not the ratio
<florian> fantasai: we might be be able to do that in a web compatible thing
<florian> fantasai: so before we add more to HTML, we should look into whether we can do that mappinng in the CSS layer
<fantasai> glazou: I really like that
<fantasai> glazou: Two things I'd like to know
<fantasai> glazou: First, when we have for some elements a placeholder to display until the element isloaded from the network, we are going to have a cahnge of aspect ratio
<fantasai> glazou: So it would be good to detect that the aspect ratio is changing from some external source like the network
<fantasai> glazou: About your a) nand b) rpoposals for the limits
<florian> q+
<fantasai> glazou: from-ratio won't allow partial value sunless you allow into calc(), so I would prefer th eunit
<franremy> q+
<TabAtkins> (The point of doing *some* aspect-ratio things in HTML is, as Greg suggested, to be even more preloader friendly.)
<fantasai> futhark: For the min-height problem, try min-max aspect ratio
<fantasai> fantasai: We thought about it, but though tthis was mroe stragithforward and easier to understand
<fantasai> fantasai: what's a min-aspect ratio? would ahve to privilege one dimension over the other
<fantasai> gregwhitworth: ....
<fantasai> astearns: Might want to limit current discussion to concerns about whethe rto add to the draft
<krit> q+
<fantasai> florian: based on what you said, I'm happy to move this forward
<astearns> ack florian
<astearns> ack franremy
<dbaron> I think I prefer option A over B, for being clearer, and I think we should eventually get from-ratio into calc()
<fantasai> fremy: I would say that from-ratio seems way easier to implement
<fantasai> fremy: ???
<fantasai> fremy: Among the two solutions, an implementatio nperspective from-ratio is way easier
<fantasai> fremy: That's all, not opposed to the unit
<fantasai> fantasai: Note that this unit exists already for gaps, we're just copying that solution here
<TabAtkins> q+
<fantasai> krit: Shoudl look at preserveAspectRatio attribute
<fantasai> florian: I think parallel between preserveAsepctRatio is with the 'object-fit' property in CSS
<fantasai> florian: Some aspects of viewbox correspond to this
<fantasai> florian: My first impression is that even if we add as properties the things that SVG already has
<fantasai> florian: These things an this, have a shorthand-longhand relatioship, so there's no conflict
<astearns> ack krit
<fantasai> florian: We need to think through it but there's no conflict
<fantasai> jensimmons: If you look at issue 333, I've dropped links to authors writeups on aspect ratios
<fantasai> jensimmons: So we need to go through all that and make sure we've thought about those comments and ideas
<fantasai> astearns: What about SVG?
<astearns> ack TabAtkins
<fantasai> jensimmons: Sara Soueidan wrote up a blog post on viewport in CSS
<fantasai> TabAtkins: I am in favor of doing this
<fantasai> TabAtkins: I want to put it WICG
<fantasai> florian: Let's incubate in the CSSWG like we always do
<fantasai> astearns: I'm going to close the discussion at this point.
<fantasai> astearns: It's break time
<fantasai> https://www.w3.org/TR/2018/WD-css-grid-2-20180804/#alignment
<fantasai> ar units ^
jensimmons commented 6 years ago

Here's an interesting request: https://twitter.com/nhoizey/status/1054712116534489089

Fluid video (that has an aspect ratio, like 16x9), with fixed-height controls running along the length of the video directly underneath. I remember this being super common in the days of flash player for video. I haven't seen this since people switched away from Flash, but perhaps it's still common.

Something like this might be the solution:

.video {
  width: 100%;
  height: calc(.5625tr + 25px);
}
tomhodgins commented 6 years ago

That syntax looks similar to the EW units discussed above. Here's a working demo mocked up using EQCSS where ew takes the place of tr from that last code example:

<div>
  <nav></nav>
</div>

<style>
  @element div {
    :self {
      background: lime;
      height: calc(56.52ew + 25px);
    }
    :self nav {
      height: 25px;
      background: hotpink;
    }
  }
</style>
<script src=https://elementqueries.com/EQCSS.js></script>

Live Demo: https://codepen.io/tomhodgins/pen/bmmEVj

aspect-ratio-fixed

Archibald2 commented 6 years ago

In issue #1173, I have suggested the following.

Instead of introducing the 'ar' unit which can relate height to width or relate width to height, code would be easier to read if 'w' is used for width and 'h' is used for height. So for example; div { min-height: 1w; } article { max-width: 1.5h }

sandstrom commented 6 years ago

@jensimmons Very happy to hear this is being worked on! 🏅

As a developer, this is an issue we've run into multiple times. For example, getting a modal window to scale with a fixed ratio depending on how much content there is in it (with current CSS toolset the best one can do is for it to expand 100% in one axis before expanding in the other).

As for the options, I think option B (tr unit) is better. I also like the suggestion by @Archibald2, of using h and w (it would fit in with other dynamic units, such as vw and vh).

Either of them (tr or w/h) would be a great addition to CSS! 💯

nhoizey commented 6 years ago

@Archibald2 I see developers already struggle with w as an actual pixels width descriptor in srcset and vw as a viewport relative width in sizes, so I'm not sure using w here would help them, even if one is in HTML and the other in CSS. I also still hope to get width descriptors (probably with w) in CSS Images Module Level 4.

On a side note, I wonder why both this issue and #1173 are still open. Is there any difference?

Yay295 commented 6 years ago

I haven't used srcset or sizes, but I don't know how vw could possibly be confusing, after you figure out what a viewport is. Could the issues people are having be due to a poor specification of srcset/sizes rather than due to a bad size unit?

nhoizey commented 6 years ago

The issue is with the very close names w and vw. But they get used to it, fortunately.

But the point here for aspect ratio is that you suggest using w in CSS for a dimension relative to an element's width, while it's already used in HTML (and I hope in the future in CSS) for the actual pixels width of an image.

Archibald2 commented 6 years ago

@nhoizey I'm coming round to thinking it would be better to use percentage lengths as with vw and vh. So here's another option:

div {
min-height: 100%w;
}
article {
max-width: 150%h
}
tremby commented 6 years ago

Hopefully this isn't too dumb a question, but what is tr? I see it and can only think of "table row".

tremby commented 6 years ago

Oh, never mind, it was a dumb question. Either the draft changed in the last day or so from ar to tr (it's "transfer ratio"), or I didn't read the draft thoroughly enough the first time!

SelenIT commented 6 years ago

@tremby it changed: https://github.com/w3c/csswg-drafts/issues/3225

Archibald2 commented 6 years ago

With regard to the draft at https://drafts.csswg.org/css-sizing-4/#ratios, I think "Intrinsic Aspect Ratios" should be changed to "Specific Aspect Ratios". While an image for example has an intrinsic aspect ratio, my understanding is that proposed 'aspect-ratio' property will specify a fixed aspect ratio for an element.

nigelmegitt commented 6 years ago

tldr:

Aspect ratio is a thing in video, and we shouldn't create new problems there. Encouraging the viewport to be a different aspect ratio to the content has an accessibility impact.

Longer version:

Just want to call out that there's a potential impact here on users of video, who might be confused by this. In video it is common for different aspect ratios to be used and to modify the size of the video element automatically based on the content being played.

If a video element is given a specific aspect ratio, and that does not match the aspect ratio of the video content being played, what should happen?

For example, video content aspect ratio is 16:9, video viewport is 4:3. Should the video get black bars top and bottom, or should the central 4:3 section be shown only, omitting the 12.5% on either side?

This is a big deal for subtitles and captions authored with specific positions in mind, if those positions are specified with respect to the video viewport. It is typical to position subtitles to avoid obscuring important action happening in the video, for example a person's face when they are talking, the ball in a sports game, etc. It is important to have a clear positioning model in this case.

At the very least, whatever the implementation does with the video in this case needs to be available to player js code so that it can try to get the positioning correct.

Apologies if this is not the right place to raise this question. It just seems that introducing aspect ratio to CSS may exacerbate this issue, or confuse users, even if it is already possible to set the size of a video element explicitly to whatever aspect ratio is needed. For example now, it is possible to set max-width: 100%; alone on a video element, and the height is resolved automatically based on the aspect ratio of the content.

Dan503 commented 6 years ago

@nigelmegitt set the height and width of the video using CSS to a square aspect ratio or something and see what happens.

It typically will display black bars but you can use object-fit to alter how the video is displayed.

nigelmegitt commented 6 years ago

@Dan503 thanks, it may well be that all we need here is an informative note directing readers who think they've found the answer to their video aspect ratio problems to the correct place, i.e. CSS Images.

ddamato commented 6 years ago

This is a use-case that an aspect-ratio unit may be helpful in: https://stackoverflow.com/questions/49525893/css-aspect-ratio-set-width-of-child-element-based-on-dynamic-parent-height

nhoizey commented 6 years ago

Fluid video (that has an aspect ratio, like 16x9), with fixed-height controls running along the length of the video directly underneath. I remember this being super common in the days of flash player for video. I haven't seen this since people switched away from Flash, but perhaps it's still common.

@jensimmons I don't think it is still common indeed, but here is at least one example with LinkedIn Learning: https://www.linkedin.com/learning/photoshop-cc-2019-new-features/photoshop-20-will-change-how-you-work

eeeps commented 5 years ago

Issue 4 in the spec asks:

aspect-ratio: attr(width px) / attr(height px);

[...] Can we just slip this aspect-ratio rule into the UA default style sheet for images, so that they have an aspect ratio while they load? This would avoid the need for extra reflows after loading.

This is an interesting idea for how to solve the same problem that the proposed intrinsicsize attribute (on <img> and <video>) is attempting to solve. intrinsicsize solves it at a different level, by setting/overriding the image's intrinsic size (or aspect ratio), rather than establishing a default extrinsic ratio for it.

So I guess first of all – I just want to cc some intrinsicsize people who have thought through this problem – @tigt @ojanvafai @loonybear

Second – I have two questions about how the proposed rule may break existing content.

Specifying width and height as percentages was valid in HTML 4.01. Is there existing content that will break if those percentages are interpreted as px (I guess?) and fed into this rule?

Currently, in order to achieve fluid sizing without aspect-ratio distortion on an image with width/height, you have to "undo" the extrinsic size set in the cross axis by setting it to auto:

<img width="300" height="200" style="width: 100%; height: auto;" />
<!-- without `height: auto` this would be locked to a height of 200px, even as the width was fluid/variable -->

I suppose this new default would obviate that: a UA default aspect-ratio would trump the height="" presentational hint, so we could just write

<img width="300" height="200" style="width: 100%;" />

and get a 3:2 fluid img (that was 3:2 even before the image loaded and an intrinsic size was known). Yay! But... is there any existing web content that relies on or expects the previous behavior? Maybe, uh, spacer gifs?

tigt commented 5 years ago

One could change the UA selector to be more like img:not([width*="%"], [height*="%"]), but I don't know if all CSS engines would run that performantly enough for every page.

Can attr() interpret as a CSS <length> falling back to px?

loonybear commented 5 years ago
  1. Maybe I didn't understand your question. But if width and height are already specified (either in pixel or percentage), intrinsicSize does not change the aspect ratio for the layout, it will only override what naturalWidth and naturalHeight return.

  2. <img intrinsicsize="300 x 200" style="width: 100%;" /> maybe? I will test it and get back to you.

long story short, if intrinsicSize is not specified, nothing is changed (unless you turn on feature policy unsized-media policy, which set the default intrinsicSize to "300 x 150"); if intrinsicSize is used it doesn't do anything more than overriding the value of the intrinsic size of the image.

eeeps commented 5 years ago

@loonybear my fault for not really asking a question! I guess my first implicit question, which you answered, was "would there be any weird interactions between intrinsicsize and this default aspect-ratio rule?" (sounds like, no 🎉). My second question is, given what you understand about the problem space, are there any problems you forsee with the proposed UA default style? The intrinsicsize explainer calls a solution built on width and height out for being “not really backwards compatible” – I've tried to think through some reasons why that might be, above, but I'm asking if you or @ojanvafai can be more specific about what was meant by this.

eeeps commented 5 years ago

Maybe it would be weird to use height and width to set intrinsic sizes, but it's perfectly fine to re-use them globally to set extrinsic ratios. And, for the purposes of no-reflows-after-image-loading,

<img intrinsicsize="300x200" style="width: 100%;" />

and (in the presence of the proposed UA default style)

<img width="300" height="200" style="width: 100%;" />

are functionally equivalent – they're just two good ways to solve the same problem. In which case, great! (and sorry for all of the comments).

jonjohnjohnson commented 5 years ago

Just wanted to make sure folks know of...

Both for commenters to learn from and for those involved then to feel free to chime in.

loonybear commented 5 years ago

aspect-ratio works on all replaced elements whereas intrinsicSize so far only works on HTMLImageElement and HTMLVideoElement. The intention is for it to work well with feature policy 'unsized-media' which deals with problems that cause layout instability (content jumping around on the web page).

But if aspect-ratio could cover all the cases we need intrinsicSize for (being able to determine the layout size before downloading the image), then I don't think there's a need for intrinsicSize.

So how would aspect-ratio achieve the case of:

<div style="width: 75vw">
  <img src="my-image.jpg" aspect-ratio="4x3" style="max-width: 100%">
</div>

i.e. we want to set the image's width to min(width of container, intrinsic width of image). Is it possible for aspect-ratio to do so before downloading any image data.

Another question would be, how does it work with responsive images, how will the naturalWidth and naturalHeight be updated if an aspect-ratio is specified?

fantasai commented 5 years ago

@eeeps So about your backwards-compat concerns in https://github.com/w3c/csswg-drafts/issues/333#issuecomment-438092951 ...

Specifying width and height as percentages was valid in HTML 4.01. Is there existing content that will break if those percentages are interpreted as px (I guess?) and fed into this rule?

I'm expecting this to be implemented in C++ rather than CSS, but in the case of CSS percentages would end up invalid here (invalidating the rule) and in C++ we would certainly want to do the same.

Currently, in order to achieve fluid sizing without aspect-ratio distortion on an image with width/height, you have to "undo" the extrinsic size set in the cross axis by setting it to auto:

Yes. I'm not proposing to change that: the width and height attributes would still map to the corresponding CSS properties. The proposal is simply that they would also map into an aspect-ratio property.

fantasai commented 5 years ago

The main concern wrt Web compat is someone putting in width and height attributes that don't correspond to the image's actual aspect ratio, and then also overriding those width and height attribute values with different width and height CSS values one of which is auto.... I don't anticipate this being particularly common, but it could happen. :)

bramus commented 5 years ago

With a huge chance of side-tracking this thread (due to not really knowing where exactly to post this reply) or the risk of proposing something that got proposed before, here goes:

Glad to see the addition of aspect-ratio being talked and discussed about, as the need is real (once wrote an extensive post on this myself).

Thinking further on this, this solution is somewhat limited: it only solves the aspect ratio problem, and nothing else outside of that.

A more broader solution – I think – could be the introduction of a val() function, which could be used to solving the aspect-ratio thing, but also other future things.

The val() function would work like the var() function (which reads the value of a custom property) but then for reading values from other properties. The val() function also differs from var() in such a way that it yields the computed value of the property. Recalculation would happen upon resize events and the like. Combine val() it with calc() and you're good to go.

In code, it would result in something like this:

.box {
  width: 100%;
  height: calc(val(width) * 16 / 9);
}

Of course it needs some more tweaking and thought: What if you want percentages (for use within rgba for example)? Perhaps a second argument that defines the requested unit (say you want percentages or ems instead of pixels) could be added? Or a whole different function that converts units could be introduced (unit() would be a nice one)? Or … — Things might easily get over-complicated, which is not really feasible I guess.

I know, it's a bit side-tracky this reply, but I do see a future for this kind of addition. Don't let this comment hinder the release of aspect-ratio though, the sooner it lands the better! Maybe it could later be retrofitted as an underlying part of aspect-ratio? Quite sure all the smart people involved will have a clear idea on this all, or will immediately see a lot of flaws in my brainfart above, as you've already pondered about it quite a lot.