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 calc-size() function #955

Open
1 task done
dbaron opened this issue May 14, 2024 · 11 comments
Open
1 task done

CSS calc-size() function #955

dbaron opened this issue May 14, 2024 · 11 comments
Assignees
Labels
Mode: breakout Work done during a time-limited breakout session Review type: working group A review request from a WG that is not part of horizontal review Topic: CSS Venue: CSS WG

Comments

@dbaron
Copy link
Member

dbaron commented May 14, 2024

こんにちは TAG-さん!

I'm requesting a TAG review of the CSS calc-size() function.

The CSS calc-size() function is a CSS function similar to calc(), but that also supports operations on exactly one of the values auto, min-content, max-content, fit-content, stretch, or contain. This allows transitions and animations to and from these values (or mathematical functions of these values), as long as the calc-size() function is used on at least one of the endpoints of the transition or animation to opt in.

Further details:

  • I have reviewed the TAG's Web Platform Design Principles
  • Relevant time constraints or deadlines: hoping to ship this sooner rather than later
  • The group where the work on this specification is currently being done: CSS Working Group
  • The group where standardization of this work is intended to be done (if current group is a community group or other incubation venue): CSS Working Group
  • Major unresolved issues with or opposition to this specification:
    • There has been some discontent about this not solving all of the problems that people hoped it would solve. It nonetheless solves a bunch of real problems and I think it's worth doing.
    • see explainer for further links / discussion, though I'm not sure any of the issues count as major
  • This work is being funded by: Google
@martinthomson
Copy link
Contributor

@hober, @LeaVerou, @plinss, and I discussed this and we have some brief feedback, some of which is really questions.

We have several concerns with the design of this function:

  • If calc-size() returns a <length>, what prevents authors from doing something like calc( ( calc-size(min-content) + calc-size(max-content) ) / 2 ) which seems to be the very thing it was designed to prevent? If that is invalid, it seems like a footgun, since these lengths are often passed around in variables, so the error will not be immediately obvious. And if it’s invalid, it begs the question, how is this better than making calc(min-content + max-content / 2) invalid while calc(min-content / 2) or calc(max-content / 2) are individually valid.

  • We are concerned with adding a parallel function to CSS that is identical to calc() with the only exception being that it supports an intrinsic sizing keyword. We think that simply allowing keywords in calc() would have been a better design, even if only one keyword type is supported and it becomes invalid when more than one are used (going from 0 to 1 is still an improvement, modulo the above concern). This leaves the door open for supporting more keywords in the future, it means all other math functions that support <calc-sum> (such as clamp()) also support intrinsic sizing keywords, and does not increase the API surface authors need to learn (especially since we suspect it’s unlikely they would ever hit that restriction).

  • Looking at the (great) compat analysis, it seems unclear whether this would be a net negative. As @dbaron points out, in most of these cases the result is either an improvement, or a very slight glitch. We are not sure that the reduction in ergonomics that something like calc-size() causes is clearly warranted from this data. But even it were, is introducing a new calc() function the best way to address it? E.g. there are other cases where transitions need to customize the interpolation on a value type-specific basis, e.g. color space for <color> transitions, perhaps some kind of per-transition/animation opt-in would be more palatable?

  • We have concerns about backward compatability. E.g. if an author specifies height: calc-size(max-content) (or height: calc(max-content)) then a UA that doesn't support the new behavior loses the height property, requiring the author to specify height twice (or more: height: max-content /* what is wanted, not animatable */; height: calc(5em * ?) /* approximate the size, but animatable (?) */; height: calc-size(max-content) /* this proposal */;)

  • Using a calc a function to opt-in to animation behavior doesn't seem readable. A different author seeing height: calc-size(max-content) will not necessarily understand the purpose of the function and may want to remove it to just height: max-content. The effect here of disabling the animation is not an obvious consequence of that change.

@martinthomson martinthomson added Progress: pending external feedback The TAG is waiting on response to comments/questions asked by the TAG during the review Topic: CSS Venue: CSS WG Mode: breakout Work done during a time-limited breakout session Review type: working group A review request from a WG that is not part of horizontal review and removed Progress: untriaged labels May 21, 2024
@dbaron
Copy link
Member Author

dbaron commented May 21, 2024

  • I just answered the first part of your first question about why not to allow mixing in [css-transitions] Transition to height (or width) "auto" w3c/csswg-drafts#626 (comment) , since I saw it there first.

  • I think the second part of the first question and much of the second question (why not just use calc() and make the mixes syntactically invalid) is answered in [css-transitions] Transition to height (or width) "auto" w3c/csswg-drafts#626 (comment) and [css-transitions] Transition to height (or width) "auto" w3c/csswg-drafts#626 (comment) , which describe the original rationale for this choice. (I agree the this definitely has arguments on both sides, though.) However, I think the response to the first question (why we shouldn't support mixes) negates some of the arguments you make about supporting mixes eventually.

  • I think that's a misreading of the compat analysis. I found three animations that were clearly worse and would probably be considered unacceptable regressions to the page designers, one that was different but not obviously worse or better, and one that was better. And that was using a sample that was extremely short on animations since it involved only page loading and not user interaction.

  • I think developers who pay attention to backwards-compatibility are familiar with the idea of repeating declarations with the one for older browsers first. That said, I suspect the reason you're raising this (that is, the only reason I see that this is different from adding any new CSS feature) is because of the connection to the next point -- that you'd like authors to use a different opt-in so that the backwards-compatibility concern (at least for CSS transitions rather than CSS animations) would be restricted to the animation itself and not the states before and after it. That's a fair point. (That said, the alternative opt-in mechanisms we discussed so far all have tricky issues as well, I think; see below.)

  • As a followup to the most recent CSSWG discussion, we opened [css-values-5] Interpolating calc-size() more generally w3c/csswg-drafts#10294 on having an additional opt-in mechanism. (After all, there's no reason that we have to have only a single opt-in; it may well be reasonable to have more than one thing that opts you in to the "new" path.) I think there are a bunch of complex design questions about an alternative, such as:

    • We want to avoid an opt-in that is too "global" because it doesn't work well for web content that mixes components built by different authors (some of which may need the new behavior and some of which may be incompatible with it)
    • Adding to the existing transition-behavior shorthand is too tied to CSS transitions; if we did this we'd need a separate opt-in for CSS Animations and Web Animations
    • Having a separate non-inherited property makes the syntax somewhat disconnected from the animation that requires it; I think mode-switching properties in CSS that have effects on other properties are generally a design mistake, both because of action-at-a-distance (with declarations from different sources combining together) and because they're not tied to the CSS cascade's overriding behavior.

    I think then there are two separate questions: do you think having the calc-size() opt-in is too unreadable to be the only opt-in, or do you also think it's too unreadable to be one of the choices for opting in? I'm not sure from your question whether you think only the first, or you think both.

@plinss plinss removed this from the 2024-05-27-week milestone Jun 10, 2024
@torgo torgo added this to the 2024-06-17-week:d milestone Jun 16, 2024
@martinthomson martinthomson removed the Progress: pending external feedback The TAG is waiting on response to comments/questions asked by the TAG during the review label Jun 18, 2024
@martinthomson
Copy link
Contributor

do you think having the calc-size() opt-in is too unreadable to be the only opt-in, or do you also think it's too unreadable to be one of the choices for opting in?

Yeah, this is really the crux of the problem that we're also grappling with. We note that CSS met recently and resolved on a separate opt-in mechanism. The remaining question we have is whether the calc-size() wrapper is necessary in light of that.

@dbaron
Copy link
Member Author

dbaron commented Jun 19, 2024

My current thinking is that I'd like to do the following:

  • support both interpolate-size (as resolved last week in [css-values-5] Interpolating calc-size() more generally w3c/csswg-drafts#10294) and calc-size() syntax
  • when describing and documenting the animation use cases, recommend interpolate-size (and use interpolate-size as the primary name of the feature, e.g., updating the explainer, updating the chromestatus entry, using it primarily blog posts)
  • document that calc-size() is used to represent the intermediate values in animations with keyword endpoints.

I think there are two reasons to want to keep calc-size():

  1. it's architecturally not really possible (at least cleanly) to have CSS animations that produce intermediate values that aren't representable in CSS. (mix() provides a future mechanism that makes this at least more palatable than it is today albeit still not ideal, but it's not yet implemented anywhere as far as I know.)
  2. The extensible web manifesto gives a number of reasons that we should bias towards exposing the mechanisms underlying things unless we have reasons not to do so; I don't think there's sufficient reason not to expose calc-size() here (even if there is good reason to suggest an alternative for a key set of use cases). (Along these lines, at the CSS face-to-face last week @kizu mentioned having non-animation use cases for calc-size().)
@LeaVerou
Copy link
Member

(Writing this comment on my own, but from what I recall about our consensus last time this was brought up)

I think there are two reasons to want to keep calc-size():

  1. it's architecturally not really possible (at least cleanly) to have CSS animations that produce intermediate values that aren't representable in CSS. (mix() provides a future mechanism that makes this at least more palatable than it is today albeit still not ideal, but it's not yet implemented anywhere as far as I know.)
  2. The extensible web manifesto gives a number of reasons that we should bias towards exposing the mechanisms underlying things unless we have reasons not to do so; I don't think there's sufficient reason not to expose calc-size() here (even if there is good reason to suggest an alternative for a key set of use cases). (Along these lines, at the CSS face-to-face last week @kizu mentioned having non-animation use cases for calc-size().)

Both of these arguments make the point that intermediate values should be representable in CSS. However, no-one proposed they should not be! Our concern was about introducing a new function to do this whose only purpose seems to be implementation convenience. There does not seem to be any author-facing reason that justifies introducing a distinct calc-size() syntax over simply using calc(). We listed several issues earlier that make the DX calc-size() quite confusing for authors. None of these issues are present when simply reusing calc() for this.

We think that reusing calc() even with constraints about the number of distinct intrinsic size keywords that can be valid within it would be a far better path forwards for authors: No new function to learn, and they would likely never even hit the limitation. The current state is that no intrinsic size keywords are allowed in calc(), so allowing one but no more than that seems like a direct improvement, and leaves the path open for supporting more in the future.

From our perspective, it seems that the only argument against reusing calc() with a limit of one intrinsic keyword max is theoretical purity (that the limitation should be clear from the syntax), which as you know, is at the bottom of the priority of constituencies.

@tabatkins
Copy link

First, I dispute that the signaling value of calc-size() can be ignored. A calc-size() is very specifically not a number and can't be used in places where numbers can; it's an intrinsic size usable only in a few specially-allowed places. This is distinct from other specialized uses of calc(), like their use in RCS with channel keywords, where the value takes some context from its surroundings but is afterwards just an ordinary number.

This also comes with a usability benefit, in that because there are behavior differences in layout algorithms based on what sizing keywords you're using, it's of some value to authors to ensure that it's clear and obvious which keyword it is being adjusted. Having it pulled out as the first argument of calc-size() accomplishes this.

Relatedly, it's just plain valuable to know that the value is an intrinsic size, of any sort; having that behavior switch hidden in an arbitrarily-complex calc() isn't ideal. (It also would mean that we could no longer define that calc() is a <length-percentage>; it would only be so conditionally, based on the absence of such a keyword.)

Second, I explained why a separate function, and not just "keywords in calc()", was useful back in the CSSWG thread that introduced this, in direct response to your comments in that thread, @LeaVerou.

If I ignore the ones related to interpolation (largely moot now), and put the signaling value to the side as well, the big remaining reason from that thread is that percentages can have intrinsic behavior, but they already have well-defined and interoperable behavior in calc() which will not smoothly interpolate. That is, if 100% ends up cyclic, interpolating from 100% to 0 will "behave as auto" for the entire duration of the transition, and then suddenly snap to 0 at the end. With calc-size() you can instead get smooth interpolation behavior from any starting size, regardless of what it is, simply by putting it as the first argument.

@plinss
Copy link
Member

plinss commented Jul 17, 2024

@tabatkins can you join us for a call to talk about this in more detail? Possibly the week of the 29th?

@tabatkins
Copy link

Sure? I'm not sure what else I can communicate that hasn't already been, but that's fine.

I'm not available Monday all day, or Tuesday afternoon. The rest of the week is fine (PT working hours)

@LeaVerou
Copy link
Member

@plinss that was meant to ping @dbaron as well, right?

@plinss
Copy link
Member

plinss commented Jul 17, 2024

Yes, @dbaron is always welcome.

We're at a F2F this week and will be off next week, and we're planning on rescheduling our regular breakouts, so we'll get back to you to schedule.

@dbaron
Copy link
Member Author

dbaron commented Jul 18, 2024

The week of July 29th I can generally do 9:00-17:30 in America/New_York (13:00-21:30 UTC), or usually to 18:00 local (22:00 UTC) if needed. I'd prefer to avoid 12:00-14:30 local (16:00-18:30 UTC) on Wednesday and to avoid 12:00-13:00 and 14:00-15:00 local (16:00-17:00 and 18:00-19:00 UTC) on Thursday. If needed I could also do other times within 6:30-22:00 local (10:30-02:00 UTC) if given a short and specific time window sufficiently in advance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Mode: breakout Work done during a time-limited breakout session Review type: working group A review request from a WG that is not part of horizontal review Topic: CSS Venue: CSS WG
6 participants