Re: [csswg-drafts] [css-color-5] How should negative percentages behave in color-mix()? (#6047)

@tabatkins 

> The minutes-bot wasn't told the issue number for this discussion, but [here are the minutes from yesterday's call](https://lists.w3.org/Archives/Public/www-style/2021Mar/0002.html):
> 
> > ## How should negative percentages behave in color-mix()?
> > github: #6047
> > chris: Sam Weinig who is implementing pointed out that can't do
> > negative percentages
> > chris: una said why don't we clip it 0-100%
> > chris: nobody wants this
> > chris: I can define it
> > fantasai: Can you make it invalid?
> > TabAtkins: Invalid matches behavior in other mixing functions
> > TabAtkins: We intend for it to be meaningless, so should be invalid
> > RESOLVED: negative percentages are invalid in color-mix()
> 
> @LeaVerou, are you saying that we should re-open the issue and change the resolution? Because the minutes are quite clear on what we decided - negative %s are invalid (and the intention of the resolution is that >100% individual percentages are invalid, too, it just didn't get caught by the resolution text). And the preceding discussion, similarly, said that when both colors give a % and they sum to >100%, we'll rebalance the %s to add to 100%, not just literally scale each as specified then add them together.

I had not realized we resolved against this, I would have argued against it. As is evident in the minutes, this appears to have been a very quick discussion, blink and you've missed it. I suppose making them syntactically invalid per the resolution is better (more feedback) than just silently clamping. This is definitely not the hill I want to die on, but I will reply to the questions you raised.

> If you think there's a very good reason why color-mix() should act like this, then presumably it applies to cross-fade() as well, and we should harmonize the specs. If you think there's a very good reason why color-mix() should act like this _that doesn't apply to mixing images_, I'd love to hear it, so I can be convinced that these mixing functions should indeed act differently from each other.
> 
> But right now I see absolutely no difference between the two. cross-fade()'s definition of "linear weighted average of each pixel's colors, in premultiplied sRGB space" is mathematically the same as "scale and add (in a particular colorspace)", so any argument you can give for why colors should act in a certain way due to the underlying math would apply to images exactly as well.

- As I pointed out, transitions already have the behavior I was proposing for handling percentages outside [0%, 100%]. I'm all for consistency, but I think consistency with something as widely deployed as transitions is far more important than consistency with a feature that's largely unimplemented, and whose one implementation doesn't even match the spec. Also, authors are more likely to draw parallels with other areas of CSS where colors are interpolated, than with a function that interpolates between images. 
- Note that, if I remember correctly, there were similar discussions around the y percentages of `cubic-bezier()`, and it turned out that authors *did*, in fact want to go outside [0%, 100%] and extrapolate (to create bouncing effects) so we changed it. It's literally zero more effort to implement (I think), and strictly more powerful. The clamping behavior is something authors can always force with `clamp()`, however if we go with clamping, there is no way to force the other behavior (extrapolation).
- In addition to consistency with transitions, and use cases, I originally argued for extrapolation as a feedback mechanism to facilitate debugging.

> Regardless, tho, my argument is at a different level - both of these functions are _mixing two (or more) things_. The fact that we can implement "mixing" as "scaling and adding" doesn't mean that "scaling and adding" is the correct mental model we should be exposing to authors; that's a leaky abstraction. Like cross-fade() does, the interface we should be exposing to authors is mixing-focused, and that implies certain things about how we interpret overconstrained % situations.

I don't think defining this around interpolation is a leaky abstraction. Interpolation as a concept is pretty high level. There are numerous other things in CSS that use interpolation so authors already need to be familiar with it. Picturing the result of `color-mix()` as a point along a gradient is far easier to conceptualize than some notion of "mixing" that does not appear anywhere else (and is easily confused with mixing paints, which is *not* a helpful model when mixing light).

> The behavior y'all are describing isn't interpolation, either, it's _arbitrary scaling and addition_ of the colors.

It's extrapolation, and the math is identical. They're the two sides of the same coin.
Could you describe what this "arbitrary scaling and addition" that you're describing is?

> That has further odd implications - it implies that if the %s sum to >100%, that doesn't get rebalanced, you just get a _super vivid/light/etc_ color. Similarly, %s summing to <100% just makes a very achromatic/dark/etc color.

How so? They are still normalized to sum to 100%. 110% and -10% sum to 100%. Nobody is proposing that the percentages shouldn't normalize.

> Unless there's a _very_ good reason otherwise, the various value-mixing operations should look as identical as possible to authors; giving authors bespoke mechanisms for what are, to them, identical operations with different value types is bad design on our part.

You just said that `cross-fade()` performs interpolation, but `color-mix()` should be explained in terms of "mixing", not interpolation (whatever that means). If that's the case and their mental model is different, why do their syntaxes need to be harmonized? If that's _not_ the case, and they are both about interpolation, then going outside [0,100%] along the same line makes sense, as you [agreed](https://github.com/w3c/csswg-drafts/issues/6047#issuecomment-791049565). Which one is it?

> I don't understand what you mean by this, either. Could you elaborate? Unless I'm misunderstanding, it's omitting a % that allows authors to avoid manually subtracting from 100%.

What I mean is there is there is still only one data point: the point along the progression. It can be expressed either as percentage of color1, or percentage of color2, or both that should add to 100% (and if it doesn't, it's normalized to be). This does not hold true if we resolve to handle sums under 100% differently.

> Tangentially, you had said in the call that there were reasons to limit color-mix() to only two colors, and I thought that I remembered you or Chris explaining why in one of the issues, but I can't find it now. Can you point me to it, or restate it? If the math of color-mix() is literally just "interpolate the components, via scaling and adding", then I'm not sure why three colors are problematic.

This was the issue, though not sure it contains all relevant discussion: https://github.com/w3c/csswg-drafts/issues/4711


-- 
GitHub Notification of comment by LeaVerou
Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/6047#issuecomment-791841410 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Saturday, 6 March 2021 02:13:07 UTC