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-values] Add clamp()? #2519

Closed
xfq opened this issue Apr 9, 2018 · 5 comments
Closed

[css-values] Add clamp()? #2519

xfq opened this issue Apr 9, 2018 · 5 comments

Comments

@xfq
Copy link
Member

xfq commented Apr 9, 2018

For background, see discussions starting at #544 (comment)


It would be useful to add a clamp() function. Two kinds of argument order were proposed in #544:

  • (min, value, max)
  • (value, min, max)

Both of them have precedents[1][2]. (I personally prefer the (min, value, max) version.)

Although authors can emulate it by combining max() and min(), the clamp() function can avoid the confusion caused by the emulation.

The behavior of clamp() on <angle> and <color> also needs some thoughts.


Links:

[1] clamp in the Boost Algorithm Library
[2] qBound in Qt

@Loirooriol
Copy link
Contributor

What if the minimum value m is greater than the maximum one M? I can see various possibilities:

m v M min(M, max(m, v)) max(m, min(M, v)) v<m ? m : (M<v ? M : v) v>M ? M : (m>v ? m : v)
3 0 1 1 3 3 3
3 2 1 1 3 3 1
3 4 1 1 3 1 1

Or maybe m and M should just be swapped if the former is greater. #544 (comment) also proposes choosing the one of m or M which is closer to v, but then what to do if they are equally close?

@tabatkins
Copy link
Member

The default should absolutely be that the min wins over the max when they're in the wrong order; CSS uses this resolution method everywhere, because usually a minimum is important for accessibility, while a maximum is more for appearance. That is, clamp(min, mid, max) is equivalent to max(min, min(mid, max)).

As I pointed out in the thread, it's not too hard to implement either of the other behaviors if you really want: if you want max to win, you can write min(max, max(min, mid)); if you want to swap them around, you write clamp(min(min, max), mid, max(min, max)). When custom functions arrive, both of those can be made ergonomic, too.

@css-meeting-bot
Copy link
Member

The Working Group just discussed clamp(), and agreed to the following:

  • RESOLVED: Add clamp(min,mid,max) with min winning over max
The full IRC log of that discussion <fantasai> Topic: clamp()
<fantasai> TabAtkins: Proposal for a clamp function to be added
<fantasai> TabAtkins: Equivalent to using min & max in combination
<fantasai> TabAtkins: but it's pretty common to do both
<fantasai> TabAtkins: And nested functions for this are a bit confusing to read
<fantasai> TabAtkins: Variations are might want max to win, which it doesn't for CSS in general
<fantasai> fantasai: Now I understand why astearns but the minmax() issue from Grid on the agenda
<fantasai> fantasai: We might want to look at that before resolving
<dbaron> fantasai: there are 2 independent issues open on grid, affecting minmax()
<dbaron> fantasai: first is an issue where the request was to have 'fr's in the min position
<dbaron> fantasai: somebody wanted to have 1fr but cap at 250px... space then goes elsewhere
<dbaron> fantasai: seemed like you might want to control the min on that fr, so you might want minmax() to take 3 arguments
<dbaron> fantasai: the min, the goal fr, and the max
<dbaron> fantasai: other issue on minmax() was that when we were working on grid level 1, somebody said that min winning over max really bothered them, with a valid use case.
<dbaron> fantasai: there are also use cases for min winning, and that's generally how CSS works, so we stuck withit for level 1, but refiled against grid level 2
<dbaron> fantasai: both of these issues are ready for working group discussion
<dbaron> fantasai: syntax for clamp() ties into these same requests
<dbaron> fantasai: if we extend minmax() to have 3 arguments to handle the 'fr' case where it makes sense to have both a min and a max, then that's the syntax we should use
<dbaron> fantasai: alternatively, if you want the 3 argument version then you have to change the name to clamp()
<dbaron> fantasai: one advantage of the minmax() name which Microsoft people came up with is that it's really clear that the min comes first and the max comes last
<dbaron> fantasai: a clamp() function doesn't have that property
<dbaron> fantasai: what's currently in the proposal for clamp() is that the order is max-min, the first one still wins, maybe that's a reasonable proposal for one where max wins
<dbaron> fantasai: for grid ... ???
<dbaron> fantasai: if we're going to try to solve them we should try to be consistent
<fantasai> TabAtkins: i think only thing that directly affects this is ordering argument
<fantasai> TabAtkins: ordering should match my proposal here
<fantasai> TabAtkins: I don't think anything else needs to care for base proposal
<fantasai> fantasai: But also I think we should use the same name, mimax() -- and maxmin() for the max-wins case
<fantasai> TabAtkins: minmax() doens't resolve to a number
<dbaron> TabAtkins: minmax() in grid is not a clamping function. It's not a mathematical function; it's an instruction to the layout algorithm.
<dbaron> fantasai: minmax() with 2 arguments is a range, minmax() with 3 arguments resolves to 1 of the arguments
<dbaron> TabAtkins: not until layout time
<dbaron> fantasai: percentages in here also don't resolve until layout time
<dbaron> TabAtkins: 3 argument is similar to the 2 argument, still specifying a range
<dbaron> fantasai: what?
<dbaron> TabAtkins: the 3 argument version in grid will still have similar behavior, a command deeply integrated into the layout function, not something usable anywhere that can take various values
<dbaron> TabAtkins: and the value space of its arguments is dramatically different from what we want to allow
<dbaron> TabAtkins: semantically similar but very different in the details and we shouldn't be trying to reuse the name
<dbaron> Rossen: how do you propose to have contain work with variables?
<dbaron> TabAtkins: clamp? It's just a shorthand for the min() and max() functions that just implements clamping in the standard CSS fashion.
<TabAtkins> s/contain/clamp()/
<fantasai> astearns: If we do have separate minmax() with three values and clamp() with three values, should have same parameter order at least
<dbaron> astearns: if we have separate minmax() with 3 values and clamp() functions I think it makes sense to have the same parameter order at least.
<fantasai> TabAtkins: Yes, I agree. Already have that in both proposals
<fantasai> astearns: Are we coming to a resolution here, to add a clamp() function with min, mid, max?
<fantasai> astearns: Are you convinced to use clamp(), fantasai?
<fantasai> fantasai: I'm not sure yet, but not objecting 'cuz not sure
<fantasai> RESOLVED: Add clamp(min,mid,max) with min winning over max
<fantasai> github: https://github.com//issues/2519

@MadeByMike
Copy link

@tabatkins does this close #581 as well? Is clamp the way forward with this?

@tabatkins
Copy link
Member

No, that's asking for an interpolate function.

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

6 participants