w3c / csswg-drafts

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

[css-grid] aspect ratio units needed #1173

Open jensimmons opened 7 years ago

jensimmons commented 7 years ago

I know there has been discussion of aspect ratio units in the past.

We need them. Badly.

Especially with CSS Grid.

Why? When? So — there are many usecases where an Author wants to maintain a specific aspect ratio in their Grid cells. They want every cell to be 4x3 or to be a square.

For example in order to make every cell a square, maybe the browser looks at both min-content dimensions (or both results of auto) — and keeps the longer of the two. Then makes the shorter of the two into the same length as the longer.

Or a similar thing to keep 4x3, or keep 16x9.

I have not had a chance to read the proposed specs. Or code up demos. I just know this comes up over and over and over. I just had yet another person ask me how to do this, and all I can say is "use viewport units and a ton of media queries". We need something better.

keithjgrant commented 7 years ago

I agree. It’s do-able with existing CSS, but it’s a kludge: http://keithjgrant.com/posts/2017/03/aspect-ratios/

keithjgrant commented 7 years ago

…as that post points out, overflow issues can get interesting. What do you do when the width is constrained, but the contents need more space than the aspect ratio would allow for? Should an aspect ratio rule be allowed to force the width wider?

Crissov commented 7 years ago

Why would you want to solve this with units?

frivoal commented 7 years ago

There as some discussion of making the svg viewbox apply to css as well. https://github.com/w3c/fxtf-drafts/issues/7

Depending on how it ends up working, you could maybe do things like this:

.grid-item {  view-box: 0 0 16 9; }

Then width: 160px; height: auto; would give you a height of 90px, and so on.

fantasai commented 7 years ago

I think this is technically a duplicate of #333?

fantasai commented 7 years ago

After some discussion with @jensimmons, I think the best solution here is to have an aspect-ratio property for the general case. For Grid, we do need a special unit because grid cells don't have properties, but it can be restricted to grid-template syntax the way fr units are.

rachelandrew commented 7 years ago

Here is a useful roundup of current aspect ratio attempts by authors.

https://www.bram.us/2017/06/16/aspect-ratios-in-css-are-a-hack/

fantasai commented 6 years ago

So, I was just thinking about this again and the problem is this: I have two columns of different widths (say 100px and 200px), and then one row indicating it wants an aspect ratio of 1:1. How tall is the row?

tremby commented 6 years ago

@keithjgrant said

I agree. It’s do-able with existing CSS, but it’s a kludge: http://keithjgrant.com/posts/2017/03/aspect-ratios/

Unfortunately this doesn't work all the time. I am having it fail on me for example when I want my cell to be square or taller, and inside this cell I want a flex which fills the full height, for vertical spacing-out of its children. Firefox is happy but Chrome is not (100% height seems to mean nothing to it in this context), and I've had to fall back to the vertical padding hack, with an absolutely-positioned content container. But this way, the content can't grow the cell if it's too long.

frivoal commented 6 years ago

@fantasai @jensimmons @rachelandrew

So, I was just thinking about this again and the problem is this: I have two columns of different widths (say 100px and 200px), and then one row indicating it wants an aspect ratio of 1:1. How tall is the row?

I've been wondering about that too. How about saying that the aspect ratio of rows is calculated from the size of implicit columns (and vice versa) if they're sized to a <length-percentage> or to a <flex>, (i.e. something that always resolves to the same size, not auto, min-content, max-content...), or to auto otherwise?

Suggested syntax: allow <number> as a <track-size>, similarly to how we're using <number> for aspect ratio in gutters.

container {
  display: grid;
  grid-auto-columns: 1fr;
  grid-template-rows: repeat(3, minmax(1.0, auto));
}

You get 3 rows and n columns depending on content. All the columns are the same width, and the height of each row is at least the same as the width of the columns, or more if the content wouldn't fit, with each row growing individually. To get all rows to grow together, change to:

container {
  display: grid;
  grid-auto-columns: 1fr;
  grid-template-rows: repeat(3, minmax(1.0, 1fr));
}

If you want to fix the number of columns instead of rows, but keep the same aspect ratio logic:

container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-columns: 1fr;
  grid-auto-rows:  minmax(1.0, auto); /* or minmax(1.0, auto), depending */
}
frivoal commented 6 years ago

Alternatively, call it out explicitly

track-size = /* curent syntax*/ | aspect-ratio( <number>  <grid-line> [ / <grid-line> ]?)
container {
  display: grid;
  grid-template-columns: 100px 50px 300px;
  grid-auto-rows: aspect-ratio(1.0 1 / 3); /* 1 * (100px + 50px) = 150px */ 
}
fantasai commented 6 years ago

Looking back over @jensimmons' comments in https://github.com/w3c/csswg-drafts/issues/333, I'm going to suggest that we a) have an aspect-ratio property, as proposed earlier, to give individual items an aspect ratio, which can then be transferred to the grid track via auto sizing b) use ar units to mean a multiple of 1fr in the other axis. This seems like it would cover most cases, but it'd be good to hear from @jensimmons and @rachelandrew if there's other cases that are commonly needed.

frivoal commented 6 years ago

an aspect-ratio property, as proposed earlier, to give individual items an aspect ratio

Would that cover minimum aspect ratio as well? meaning that the element maintains the aspect ratio if it is underfilled, but that it does grow rather than overflow if there's too much content?

Assuming it solves that, I'm not necessarily opposed to the idea, but I think we should resume exploring https://github.com/w3c/fxtf-drafts/issues/7 before we lock in on that, because it seemed that that approach could give us aspect ratio control (and more) as well.

use ar units to mean a multiple of 1fr in the other axis

That sounds reasonable. I wonder how it compares to the aspect-ratio() function I suggested in https://github.com/w3c/csswg-drafts/issues/1173#issuecomment-362476386 in various use cases. Your syntax is much simpler and probably hits the number 1 use case, mine allows for being explicit about what you want to calculate the ratio from. If that's not useful, then my syntax is overkill, but if that is, maybe it's worth it.

tobireif commented 6 years ago

Another aspect ratio ticket: By @fantasai from July 20 2016: https://github.com/w3c/csswg-drafts/issues/333

In that ticket, @ewanm89 suggested this:

height: 100ew; to make something square

tobireif commented 6 years ago

(Where "ew" stands for element width percentage.)

tobireif commented 6 years ago

I hope this would apply to Flexbox as well (I recently needed always-square cells in Flexbox layout).

Should there be a Flexbox label in addition to the Grid label?

tobireif commented 6 years ago

I hope we'll soon get a solution, there even is a website generating a hack: http://ratiobuddy.com/

ewanm89 commented 6 years ago

yeah, old padding hack is fairly well known, and litters the code with extra divs while taking the content out of the page flow with a position absolute, very fair from a good solution.

tobireif commented 6 years ago

Some versions of the hack don't require a wrapper element

But they're all hacks.

Looking forward to having a nice native solution ...

Dan503 commented 6 years ago

If there is going to be an aspect-ratio property then there also needs to be min-aspect-ratio and max-aspect-ratio properties. I see myself using max-aspect-ratio ("max" meaning it can grow relatively taller but not wider) far more than I would use aspect-ratio.

There are min and max aspect ratios for media queries, they should be modeled after those values.

Without min and max versions it becomes difficult to manage text that doesn't fit inside the normal aspect ratio.

tobireif commented 6 years ago

If there is going to be an aspect-ratio property then there also needs to be min-aspect-ratio and max-aspect-ratio properties.

No need for more two properties, the min and max could be part of the value

Also perhaps both the aspect ratio and the min & max could be part of the value (as opposed to a new property).

Also see all "minmax" in the above comments.

jensimmons commented 5 years ago

I wrote a bit about this on Twitter, and got a bunch of responses from web developers: https://twitter.com/jensimmons/status/1053004310840266752

There have been some blog posts written by developers, articulating their desires. Here are two: https://blog.frankmtaylor.com/2018/07/20/when-properties-compete-how-css-sets-dimensions/ https://www.sarasoueidan.com/blog/svg-art-direction-using-viewbox/

I believe there's more in the Responsive Images Community Group / other Community Group discussions. I plan to read through that stuff to see what other needs might be articulated to make sure we are meeting them. And to look for words to possibly use when bike shedding names.

Archibald2 commented 5 years ago

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
}
nhoizey commented 5 years ago

Like I said in #333 (why are both still open?):

@Archibald2 I see developers already struggle with w as a CSS pixel based 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.

Dan503 commented 5 years ago

To everyone saying that they want %w and %h units:

The new unit is being locked down to CSS Grid like the fr unit is.

%w and %h, though awesome and I really want them myself, opens up huge cans of worms like "I want to use %w and %h to set font size!" Which (though so totally would be awesome) is about the biggest can of worms you can possibly open!

The bigger the can of worms that gets opened the longer it takes for the new CSS to land in browsers.

As for those wondering why https://github.com/w3c/csswg-drafts/issues/333 is still open, they are different issues.

333 is meant to be focused on adding a new aspect-ratio property that can be used more generically across CSS. This issue is focused on adding a CSS Grid only tr unit so that grid template rows and columns can be sized based on an length transfer rate.

It's not one or the other, they are planning on adding both features to CSS.

Dan503 commented 5 years ago

From https://github.com/w3c/csswg-drafts/issues/333#issuecomment-431824461:

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.

Since padding, border, and margin are all attached to either a horizontal or vertical side, I'm wondering if the tr unit could be extended to those properties as well to solve this.

from-ratio requires the whole box to be sized into an aspect-ratio, a tr unit would not.

Dan503 commented 5 years ago

from-ratio requires the whole box to be sized into an aspect-ratio, a tr unit would not.

Although if there was a way to make aspect-ratio have no effect on the box itself using min-width, min-height, max-width and max-height then from-ratio would work just fine for this purpose and tr can remain restricted to CSS Grid.

timuric commented 5 years ago

I would like to share another common use case that needs aspect ratio units. There is a common problem with layout reflows when the layout is relying on the height of the image. Probably we all have seen a jumping page over the slow network caused by the gradual loading of the images. The jumping layout have create unpleasant and disorienting effect and not to mention the UI freezes caused by the reflow. I believe having easy control of aspect ratio would help many developers create a more pleasant page loading experience. But perhaps the need for aspect ratio control goes beyond css grid?

valtlai commented 5 years ago

@timuric ~See intrinsicsize attribute.~

Updated:

See WICG/intrinsicsize-attribute#16:

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

The spec: https://drafts.csswg.org/css-sizing-4/#ratios

frivoal commented 4 years ago

Given that we now have an aspect-ratio property, are we still exploring the idea of aspect ratio related units as well, or can we close this?

Archibald2 commented 4 years ago

Given that we now have an aspect-ratio property, are we still exploring the idea of aspect ratio related units as well, or can we close this?

I agree to closing this.

Dan503 commented 4 years ago

The main argument I'm seeing in the thread is so that aspect ratio can be applied to CSS Grid templates.

I'm pretty sure using auto in the grid template and aspect-ratio on the grid cell elements would cover most use cases.

I can't really think of a scenario where I couldn't use aspect-ratio on the child cell to get the desired layout.

rachelandrew commented 4 years ago

I wonder whether if we get into a position of being able to style grid areas in some way, this may come back as a requirement. At the moment you have to put an item in the track in order to style an area, but in future maybe not.

Dan503 commented 4 years ago

The other main scenario is wanting to style things based on the width/height of the element.

For example, it would be absolutely amazing if we could write this to create text that modifies in size based on the width of the element:

.responsive-text {
  font-size: clamp(1rem, 2%w, 5rem);
}

2%w being the exact same value as what width: 2%; would equate to.

2%h would be the exact same value as what height: 2%; would equate to.

That isn't "aspect-ratio" though so maybe needs a separate ticket, or maybe we just rename this one?

dvoytenko commented 4 years ago

@Dan503 I agree. The font-size relative to width or height feels like a pretty different ticket. This is somewhat reminiscent of the CSS container queries efforts. This problem does arise a lot in the aspect-ratio context, but not limited to it.