w3c / csswg-drafts

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

using special values like max-content in functions #5554

Open bryanrasmussen opened 3 years ago

bryanrasmussen commented 3 years ago

I would like some clarification on some issues, I was recently looking at min, max, clamp functions and in my naive estimation of how they work they should be able to take as a parameter any thing that results in a value with a unit of measurement.

In the browsers I have tested you can of course use values that come from functions inside of other functions, thus you can use the result of a calc in a variable inside a min function.

Many different properties where math functions are usable have special value keywords - for example max-content, min-content in width.

Or something like the fit-content function.

In my naive consideration it seemed obvious to me that max-content can be used inside of a min function, given that fit-content is described as fit-content(stretch) i.e. min(max-content, max(min-content, stretch)) in css-sizing-4, that is to say I thought of fit-content as a bit of syntactical sugar so that developers if they wanted fit-content functionality wouldn't have to write it themselves all the time, or more to the point that clamp was a bit of syntactical sugar for an operation that developers might want to do, as is implied by example 31 of css-values-4 which says:

An occasional point of confusion when using min()/max() is that you use max() to impose a minimum value on something (that is, properties like min-width effectively use max()), and min() to impose a maximum value on something; it’s easy to accidentally reach for the opposite function and try to use min() to add a minimum size. Using clamp() can make the code read more naturally, as the value is nestled between its minimum and maximum:

.type { / Force the font-size to stay between 12px and 100px / font-size: clamp(12px, 10 * (1vw + 1vh) / 2, 100px); }

Following this naive consideration I expected that if doing min(max-content - 10px, 200px) it should figure out what max-content is in the context used and perform the calculations, but in testing neither Mozilla nor Chrome do this - I raised an issue on bugzilla just to hear if they could point me out that there was a part of the specs I was unfamiliar with that meant my expectations were totally out of whack https://bugzilla.mozilla.org/show_bug.cgi?id=1667306 where it was suggested I raise the issue here in order to be able to define how it should work.

As was noted in the discussion about the bug-report this would open up interesting animation possibilities, the more I think about it I can see uses (for specifically max-content) in utility classes that can be added to parts of a subtree to calculate out their size in the relation of what encloses them. But really it seems a point of clarity to have every keyword that returns a value potentially consumable by a function at a particular property should actually be consumable by the function - since min-content and max-content return lengths those keywords should be able to be passed as properties to whatever function we want to use to set the width.

fantasai commented 3 years ago

Keywords can't be used inside the math functions: they only replace things like <length-percentage> with a function that effectively outputs a combination of length and percentage. Keywords, which aren't part of <length-percentage> but are a separate type of value, can't be used in such functions. See e.g. https://www.w3.org/TR/css-sizing-3/#preferred-size-properties which defines width as auto | <length-percentage> | min-content | max-content | fit-content(<length-percentage>) and https://www.w3.org/TR/css-values-3/#calc-notation and https://drafts.csswg.org/css-values-4/#math which define the syntax of calc().

We agree it would be nice to allow calculations with keywords, but it's actually quite difficult because the keywords can map to rather complex behaviors. We'd like to be able to do that someday--it's been on our wishlist since calc() was first introduced--but it's not something we're ready to tackle yet.

bryanrasmussen commented 3 years ago

Ok, I guess that's fair enough, although what my thinking was that when https://www.w3.org/TR/css-values-3/#calc-notation says "It can be used wherever <length>, <frequency>, <angle>, <time>, <percentage>, <number>, or <integer> values are allowed." it meant that it would be used at a property - like width - not limiting what it could intake. So my theory was that as max-content can be used at width, and max-content will output a length, then max-content will be usable as an input to min, max, clamp, calc etc. on the width property.

We agree it would be nice to allow calculations with keywords, but it's actually quite difficult because the keywords can map to rather complex behaviors.

I haven't done international technical standardization, but I have done international financial standardization (UBL, working for Denmark) so I can certainly recognize that what I would like to see just might not work the way I was hoping!

Back to my naive expectation I was hoping that it would be possible to add some statement like:


Any keyword usable where one of these functions is usable that returns a value usable by these functions can be used in these functions with the following rules - the keyword should be evaluated as if it were being applied directly on the property to determine what its output value should be, thus if for example max-content when used in a width property would return 250px then width: calc(max-content - 25px) would end up being width: 225px.


However, if there are various reasons that something simple (perhaps it's simplistic) like that won't do the trick then I guess I will have to be satisfied with the knowledge that you would like to make it work and undoubtedly will some day.

Thanks, Bryan Rasmussen

Loirooriol commented 3 years ago

the keyword should be evaluated as if it were being applied directly on the property to determine what its output value should be, thus if for example max-content when used in a width property would return 250px then width width: calc(max-content - 25px) would end up being width: 225px.

I think that may be too simplistic. Keywords don't just "return" a length, they compute as-is and may be affected by other properties. For example, with: auto with justify-self: stretch may be different than with justify-self: start. In order to know the final value, we may have to perform an initial layout with just the keyword in order to find the used value, and then layout again with the full expression. The problem is that the used width value is influenced by min/max-width, but I don't think they should be taken into account when substituting the value of a keyword. So it needs to be defined carefully.

I think this can be more doable for min-content and max-content, but there are so many things depending on width/height computing to or behaving as auto, which make that case trickier.

bryanrasmussen commented 3 years ago

I think that may be too simplistic

yeah, I was afraid of that, but thanks for some insights there showing why it was too simplistic :)