Skip to content

[css-transitions][css-animations][web-animations] Add control of colorspace used for transitioning colors #7063

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

Open
svgeesus opened this issue Feb 16, 2022 · 25 comments

Comments

@svgeesus
Copy link
Contributor

svgeesus commented Feb 16, 2022

( Spun out from #7035 )(similar to #7062)

Currently, all color transitions happen in gamma-encoded sRGB space. There is a need to preserve this as a default, for Web compat. However, CSS Color 4 defines a bunch of other color models, which exceed the very limited gamut of sRGB, and there is a need to add control of the color space used for interpolation which is currently unspecified:

  • to avoid needless conversion to sRGB, dropping the more saturated colors
  • because interpolating in gamma-encoded space gives overly dark midpoint colors
  • because some color spaces give better results than others, which kind of varies depending what the start and end colors are, so stylesheet authors need the flexibility to choose.

As this is a common requirement, CSS Color 4 defines a <color-interpolation-method> token and associated color interpolation math; this has already been used in the grammar for `color-mix() in CSS Color 5 and in linear, radial and conic gradients in CSS Images 4.

So this issue proposes to add a new property, initial value auto:

transition-interpolation: [ auto | <color-interpolation-method> ]#

and also to add this to the <single-transition> shorthand. There is no ambiguity (unlike time) so it can go in any order in the shorthand.

@svgeesus svgeesus added the css-transitions-1 Current Work label Feb 16, 2022
@dbaron dbaron added css-transitions-2 and removed css-transitions-1 Current Work labels Mar 3, 2023
@dbaron
Copy link
Member

dbaron commented Mar 3, 2023

I think we should be looking at css-transitions-1 as feature complete, and looking at this for css-transitions-2.

@svgeesus
Copy link
Contributor Author

svgeesus commented Mar 7, 2023

Thanks, David. Is there agreement that this is the correct approach?

If so, would you like a PR to review, or should I just add it?

@dbaron
Copy link
Member

dbaron commented Mar 7, 2023

I think it probably requires some amount of discussion, though I haven't thought about the issue. My comment above was part of triaging css-transitions-1 issues in the hope of getting that spec to advance.

@w3c w3c deleted a comment from Paulorenatomiguel Mar 7, 2023
@LeaVerou
Copy link
Member

LeaVerou commented Mar 7, 2023

Agreed this should be in css-transitions-2.

@svgeesus
Copy link
Contributor Author

svgeesus commented Mar 22, 2023

There was related discussion in another issue where I said:

We could add transition-interpolation: [ auto | <color-interpolation-method> ]# and animation-interpolation: [ auto | <color-interpolation-method> ]# properties

To be clear, those would be added in CSS Transitions and to the keyframe syntax in CSS Animations respectively, right?

If so, I think you'd also need to define how they end up getting represented in Web Animations KeyframeEffect objects (possibly be adding another global keyframe attribute like offset etc. as in the last part of the informative note here).

@svgeesus
Copy link
Contributor Author

svgeesus commented May 4, 2023

Agenda+ to get CSSWG resolution on this.

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed [css-transitions] Add control of colorspace used for transitioning colors.

The full IRC log of that discussion <bramus> chris: css color-4 add something that others spec can reference: color interpolation method
<bramus> chris: already used for gradients
<bramus> chris: proposeal to add same token to animations, transitions, and web animations
<bramus> chris: proposal since March without no comments
<bramus> chris: cant think of other way to do it
<emilio> q+
<bramus> emilio: the idea is to add a transition-interpolation property?
<flackr> q+
<bramus> chris: yes
<bramus> chris: same for animation-interpolation
<bramus> emilio: so it needs to be a list?
<bramus> chris: yes
<bramus> emilio: dont know, maybe this should be in keyframes?
<bramus> chris: that is part of the proposal
<bramus> emilio: feels weird that this is color specific but property name does not give hint
<bramus> chris: can put color in there
<bramus> emilio: could be confused otherwise
<bramus> +1
<bramus> emilio: other than that seems reasonable
<Rossen_> ack emilio
<bramus> chris: brian also added proposal for web animations in the issue
<bramus> emilio: do we expect a lot of ppl setting this to anything other than oklab?
<bramus> chris: that gets us in the whole webcompat issue
<flackr> q-
<bramus> chris: talking about an opt in
<bramus> chris: oklab and oklch will be obvious choices
<fserb> I think adding color to the name makes sense. (nit: Is it a problem to add "auto" on the shorthand?)
<bramus> emilio: if you do color-mix with two oklab colors, they mix in oklab right?
<bramus> chris: yes
<bramus> emilio: (???)>
<bramus> chris: doesnt matter how you specify the orig colors. you can mix in other spaces
<bramus> emilio: maybe default should be oklab?
<bramus> chris: would be nice, but people have existing content
<bramus> emilio: maybe auto can do the right thing based on the defined colors?
<bramus> chris: auto means that legacy srgb mix in srgb. non-legacy colors mix in oklab.
<fserb> I think auto already does what emilio wants.
<bramus> Rossen_: in terms of feature itself, do you agree emilio? then can sweat details.
<flackr> q+
<bramus> emilio: seems reasonable, other than prop name
<bramus> chris: agree
<bramus> emilio: do we want to allow interpolationg different properties differently?
<bramus> emilio: eg background-color and color
<bramus> chris: i understand the requirement
<bramus> chris: if its about the keyframes, it means it applies to all color interpolations. a separate vlaue for each one, would need a ton of new properties
<Rossen_> ack flackr
<bramus> flackr: could we specify this as part of the color?
<flackr> q-
<bramus> chris: we are not going to solve this in 5 minutes
<bramus> Rossen_: good suggestion
<bramus> fantasai: so proposal is to add both transition-interpolation and animation-interpolation, where you can put the last one in a keyframe too?
<bramus> chris: yes
<bramus> fantasai: we also hav esuggestion from emilio to do it per property
<bramus> fantasai: this could be an addition?
<bramus> flackr: would affect the syntax
<bramus> emilio: need to know if we want this in the future
<bramus> fantasai: two possible ways to go about it, is to incorporate it in the color (cfr. flackr) and another option is to do sth similar as we do with transition
<bramus> chris: the latter seems like a better solution
<bramus> chris: would like to see it written out
<bramus> Rossen_: looks like this is expanding beyond orig proposal
<bramus> Rossen_: lets take back to issue
<bramus> chris: yes
<fantasai> s/with transition/with transition, and list out the properties named e.g. animation-color-interpolation: oklab color background-color sRGB outline-color, ...; /
<bramus> Rossen_: dont see issue we can tackle in 2 minutes …

@LeaVerou
Copy link
Member

LeaVerou commented May 24, 2023

Assuming this property is list-valued, like all other transition/animation properties then it's already possible to use different color interpolation methods per property, at least for transitions. For animations it would be a little more involved, but still possible. Also, I think that's a bit of an edge case, not something to center the design around. As long as it's possible, it's fine.

Agree with renaming to *-color-interpolation, though a generic *-interpolation property may allow for more future expansion. OTOH I cannot envision what such future expansion could look like: for any other value, when you want to control how it interpolates you use *-timing-function. However, we could use *-interpolation-color instead of *-color-interpolation so that if such cases emerge we can define a *-interpolation shorthand with longhands.

@astearns astearns removed the Agenda+ label Jul 10, 2023
@milasudril
Copy link

milasudril commented Jul 23, 2023

Well, this is not only related to transitions. It is also related to all sorts of compositing. Thus, an idea is to have a CSS color-rendering-mode property that affects compositing, transitions, gradient and all color related attributes.

color-rendering-mode

Supported values:

  • legacy: This value is default. Ihen using this mode alpha blending and gradients are broken as required by old specification.
  • linear: Color are blended and specified in linear RGB space, unless otherwise specified. Enabling this mode is a recommended best practice. If you specify #808080, the color will be slightly brighter than in legacy mode. It is possible to specify a color values using the legacy definition as such
  • color-rendering-mode: linear; color: sRGB(#808080)

Notice that this only affects the interpretation of #808080, which will enter the rendering pipeline as roughly #404040. Blending and gradient rendering is still performed in linear space.'

You would typically use color-rendering-mode as you use the border-box property:

{box-sizing: border-box;width: 100%;border: solid #5B6DCD 10px;padding: 5px;}

Which I also highly recommend using.

@LeaVerou
Copy link
Member

LeaVerou commented Jul 23, 2023

@milasudril Gradients have their own interpolation space, specified on the gradient itself. Also, compositing and interpolation are different use cases that often require different color spaces. Lastly, your proposal only covers sRGB (linear and gamma-encoded) which is not sufficient to cover most interpolation use cases, as neither of these are perceptually uniform spaces.

Your example with color: sRGB(#808080) makes me wonder if you have looked at any of the CSS Color specifications, as this is not at all how color works in CSS. If you are trying to specify a linear sRGB color with all coordinates 0x80, in CSS you would do that via color(srgb-linear .5 .5 .5).

@milasudril
Copy link

@LeaVerou the idea behind color: sRGB(#808080) is that, since we said that rendering mode is linear, the meaning of all color attributes that matches the current selector changes. It is like specifying the properties of the entire pipeline, like what GL_FRAMEBUFFER_SRGB, or what Vulkan does. But if the designer is used to work with sRGB values, it is useful to have some feature to specify color values "the old way".

@LeaVerou
Copy link
Member

@milasudril Please keep in mind that the Web and its use cases are fundamentally different from C++ rendering pipelines in a number of ways. This thread is about the relatively straightforward change of extending the control CSS already provides over interpolation color space to CSS transitions. If you want to change how color works in CSS as a whole, please open a new issue, provide use cases that justify such a substantial change, as well as a plan for backwards compat with existing web content. This issue is not the place for this discussion.

@svgeesus
Copy link
Contributor Author

the idea behind color: sRGB(#808080) is that, since we said that rendering mode is linear, the meaning of all color attributes that matches the current selector changes.

Tying together how a color is specified and how it is manipulated like that is a design flaw. The current design carefully avoids that.

It is like specifying the properties of the entire pipeline,

Cascading style sheets from different origins into one design is fundamentally at odds with the "change everything at once" model you are proposing.

@milasudril
Copy link

milasudril commented Jul 24, 2023

@LeaVerou Sure, that is a different topic, but I think that solving root causes, everything else would get a much cleaner solution. By the way, is suggesting a linear rendering mode for CSS, or is that to be discussed in a different forum?

@LeaVerou
Copy link
Member

LeaVerou commented Nov 2, 2023

Some notes (transition also implies animation unless otherwise specified) after an impromptu breakout with @svgeesus:

  • It should be transition-color-interpolation unless we plan to extend it in the future.
  • Assuming <color-interpolation-token> becomes part of the respective shorthands and can be specified in any order, we may end up having disambiguation problems with idents and we may need to define that in is reserved (cannot use it as an animation name) and we cannot define a property named in. OTOH maybe this is a non-issue as it’s always followed by a color space id?
  • We need to decide what the initial value would be. Same problem as gradients: should we go with better interpolation across the board, or maximize compat? I'd wager the compat issues are even smaller here, since a) it's usually a transient part of the UI and b) a compat issue with gradients is when they're used for color pickers, which is a non-issue here.

@birtles
Copy link
Contributor

birtles commented Nov 2, 2023

Sorry, on my phone so I might not have read up on the context properly, but two quick questions arose for me:

  • If we have separate animation and transition properties, how do you specify the mode for script generated animations? i.e. animations generated using the Web Animations API?

    Ultimately transition and animation properties just generate Web Animation objects so I think we'd either need to map the mode onto something on the API or we'd need a property independent of transitions and animations whose computed value Web Animations can refer to when interpolating.

  • It would be nice if we didn't have to disallow in as an animation name. It seems pretty likely that someone is using that already (e.g. when defining an in animation and an out animation).

@LeaVerou
Copy link
Member

LeaVerou commented Jun 19, 2024

Proposal

Given that we now have transition-behavior to provide parameters about how interpolation happens (currently only supporting normal and allow-discrete values), I suggest we reuse that and add a <color-interpolation-method> as part of its values.

Its syntax would then become:

<transition-behavior-value> = normal | [ allow-discrete || <color-interpolation-method> ]

It’s concerning that there is no animation-behavior counterpart, I will open a new issue as this seems like it may be an omission. (✏️ Done: #10469)

@svgeesus
Copy link
Contributor Author

That looks good to me.

CSS Color 4 defines the <color-interpolation-method> token and associated color interpolation math; this has already been used in the grammar for `color-mix() in CSS Color 5 and in linear, radial and conic gradients in CSS Images 4. So re-using it here as well is clearly the right approach.

@svgeesus svgeesus added the css-animations-1 Current Work label Jun 19, 2024
@svgeesus svgeesus changed the title [css-transitions] Add control of colorspace used for transitioning colors [css-transitions][css-animations] Add control of colorspace used for transitioning colors Jun 19, 2024
@birtles
Copy link
Contributor

birtles commented Jun 20, 2024

As I followed up on #10469, if we go with this approach, we'll also need to define a corresponding property on the Web Animations API for these properties to map to (see my previous comment).

@birtles birtles added web-animations-2 Current Work css-animations-2 and removed css-animations-1 Current Work labels Jun 20, 2024
@birtles birtles changed the title [css-transitions][css-animations] Add control of colorspace used for transitioning colors [css-transitions][css-animations][web-animations] Add control of colorspace used for transitioning colors Jun 20, 2024
@LeaVerou
Copy link
Member

As I followed up on #10469, if we go with this approach, we'll also need to define a corresponding property on the Web Animations API for these properties to map to (see my previous comment).

Yup, that seems orthogonal though. Anything we come up with would require changes to the Web Animations API.

@birtles
Copy link
Contributor

birtles commented Jun 22, 2024

As I followed up on #10469, if we go with this approach, we'll also need to define a corresponding property on the Web Animations API for these properties to map to (see my previous comment).

Yup, that seems orthogonal though. Anything we come up with would require changes to the Web Animations API.

Unless we decide to go with a color-interpolation-like property—that wouldn't require any changes to the API.

@LeaVerou
Copy link
Member

As I followed up on #10469, if we go with this approach, we'll also need to define a corresponding property on the Web Animations API for these properties to map to (see my previous comment).

Yup, that seems orthogonal though. Anything we come up with would require changes to the Web Animations API.

Unless we decide to go with a color-interpolation-like property—that wouldn't require any changes to the API.

That’s highly unlikely, since, as explained many times before, different use cases require different color interpolation settings.

@birtles
Copy link
Contributor

birtles commented Jun 24, 2024

That’s highly unlikely, since, as explained many times before, different use cases require different color interpolation settings.

My apologies, I haven't seen that context.

I had a think about this and I'm afraid I don't think -behavior is the correct approach here.

The main issue is a layering one. transition-behavior affects what animations get generated in the first place. As a result, it doesn't really make sense to map it to a property on a generated animation. It answers the question of "What animations get generated?", not "How do they behave?".

We could still add a behavior property to animations with a default value of allow-discrete and then define that animations ignore any discrete properties listed in their keyframes (or subproperties of shorthands listed in their keyframes) but it wouldn't really be doing that same thing as transition-behavior which simply prevents animations from being generated in the first place.

Furthermore, it would complicate using the behavior property since authors would need to be sure to preserve the initial allow-discrete value when specifying additional interpolation options.

Personally I think adding a very generic sounding behavior property to the API would also be unfortunate when something like interpolation would be more intuitive to both read and write.

All said, I think Lea's original suggestion of adding a separate animation interpolation properties (#7035) is preferable here and transition-behavior should remain something specific to which transitions are generated.

@LeaVerou
Copy link
Member

@birtles I get the distinction you’re drawing, but I worry it’s largely philosophical and not evident in the naming of transition-behavior, so in practice it will just confuse authors (_which property was it that I use for that flag? transition-behavior or transition-interpolation?) If anything, -behavior seems more fitting for what we're discussing here than for allow-discrete.

I wonder if we can change the name of transition-behavior or if it’s too late. We could do some compat analysis and check that out.

Furthermore, it would complicate using the behavior property since authors would need to be sure to preserve the initial allow-discrete value when specifying additional interpolation options.

Oh absolutely, that would be terrible ergonomics. It’s also unclear whether there are use cases for disabling discrete animations. If we were to go that route, I suspect allow-discrete would be on anyway, and either it would not be an allowable value, or for consistency you could specify it explicitly if you wanted, but it would not make a difference. Having to specify allow-discrete every time you set a color interpolation space is absolutely dreadful DX, and I was never proposing that.

@birtles
Copy link
Contributor

birtles commented Jun 25, 2024

@LeaVerou That's great that we're on the same page about not having to preserve allow-discrete. No doubt you can think of many better ideas for ways to avoid that than me!

However, I think there's still a fundamental layering issue with regards to repurposing transition-behavior.

Suppose we add animation-behavior to CSS Animations and a behavior property to the Web Animations API. For now, let's assume that behavior is a property of an animation in the general sense (since from an API/implementation point of view CSS transitions and CSS animations are subclasses of Animation) and we map transition-behavior and animation-behavior onto that property.

UAs apply transition-behavior's allow-discrete value when they determine which animations (transitions) to generate.

If we have:

div {
  text-wrap: wrap;
  transition: all 1s;
  transition-behavior: allow-discrete;
}
div:hover {
  text-wrap: balance;
}

Then when the div is hovered, we're going to generate a transition for the text-wrap-style property.

Suppose we spec that UAs set the generated CSSTransition's behavior property to "allow-discrete" in this case. Firstly, this seems redundant (the very existence of the transition is the application of the transition-behavior: allow-discrete) but let's ignore that for now.

This property would need to be mutable so authors can change the color interpolation mode but if you change behavior to "normal" in this case would the CSSTransition disappear? That would be surprising and I'm not even sure we have a means for representing an orphaned animation like that. We could make the animation start skipping discrete properties in its keyframes but then we're doing something new that is different to transition-behavior (which controls which transitions are generated).

However, it gets possibly more awkward when we consider where this property actually lives. Presumably, we want to be able to change the color interpolation space between pairs of values. That is, like animation-timing-function and animation-composition, you should be able to specify animation-behavior on individual keyframes. As a result, it would be possible to write content like:

@keyframes anim {
  from {
    animation-behavior: allow-discrete;
    text-wrap: wrap;
  }
  50% {
    text-wrap: balance;
  }
  to {
    text-wrap: wrap;
  }
}

With that setup, however, making the transition disappear when behavior becomes "normal" becomes impossible and we're left doing something that is different from how transition-behavior: normal actually behaves.

Perhaps there are good solutions to all these issues but so far my impression is that transition-behavior is doing something too different to color interpolation modes to be able to be reused here. I certainly appreciate the desire to re-use it, however. It would be nice if we could—I'm just not (yet) convinced we can.

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

7 participants