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-color-5] Edge cases for color-mix() percentage serialization questions #10772

Open
weinig opened this issue Aug 23, 2024 · 8 comments
Open
Assignees
Labels
Agenda+ css-color-5 Color modification

Comments

@weinig
Copy link

weinig commented Aug 23, 2024

The current text for serializing color-mix() states:

The serialization of the declared value of a color-mix() function is the string "color-mix(in ", followed by the specified <color-space> in all-lowercase, followed by ", ", followed by the first specified color, followed by a space, followed by the specified (un-normalized) first percentage (unless both percentages are 50%), followed by ", ", followed by the second specified color, followed by the specified (un-normalized) second percentage (unless the two specified percentages add to 100%), followed by ")".

Following the principle of shortest serialization, the second percentage is typically omitted, even if explicitly specified.

Directly after that, in example 43, the first example seems to contradict this:

For example, the serialized declared value of

  • color-mix(in oklab, teal, peru 40%)

would be the string "color-mix(in oklab, teal 60%, peru)".

The text states it should use the "un-normalized" values. The value of 60% would only be discovered during the normalization (specifically, step 4)).

So it seems like we need a slightly more complicated serialization rule. The following wording needs work, but I think mostly gets to the intent:

The serialization of the declared value of a color-mix() function is the string "color-mix(in ", followed by the specified in all-lowercase, followed by ", ", followed by the first specified color, followed by a space, followed by the serialization of the first percentage (see below), followed by ", ", followed by the second specified color, followed by the serialization of the second percentage (see below), followed by ")".

(note for below, calc() values are consider to be unknown, so are NEVER equal 50% and never sum with something else to equal 100%.)

The serialization of the first percentage of a declared value of a color-mix() function is defined to:

  • If BOTH the first percentage p1 and second percentages p2 are specified:
    • if both p1 equals 50% and p2 equals 50%, nothing is serialized. (a)
    • else, p1 is serialized as is. (b)
  • else if ONLY the first percentage p1 is specified:
    • if p1 is equal 50%, nothing is serialized. (c)
    • else, p1 is serialized as is. (d)
  • else if ONLY the second percentage p2 is specified:
    • if p2 equals 50%, nothing is serialized. (e)
    • if p2 is not calc(), the value of 100% - p2 is serialized. (f)
    • else, nothing is serialized. (g)
  • else if NEITHER is specified:
    • nothing is serialized. (h)

The serialization of the second percentage of a declared value of a color-mix() function is defined to:

  • If BOTH the first percentage p1 and second percentages p2 are specified:
    • if neither p1 nor p2 is calc(), and p1 + p2 equals 100%, nothing is serialized. (i)
    • else, p2 is serialized as is. (j)
  • else if ONLY the first percentage p1 is specified:
    • nothing is serialized. (k)
  • else if ONLY the second percentage p2 is specified:
    • if p2 equals 50%, nothing is serialized. (l)
    • if p2 is not calc(), nothing is serialized. (m)
    • else, p2 is serialized as is. (n)
  • else if NEITHER is specified:
    • nothing is serialized. (o)

(to make this somewhat easier to grok, below is a pretty comprehensive list of specified value serializations with a comment to the right explaining which rules it is used for each percentage).

color-mix(in srgb, red 50%,       blue 50%)          -serializes to-     color-mix(in srgb, red, blue)                     // [a & i] both 50%
color-mix(in srgb, red 10%,       blue 90%)          -serializes to-     color-mix(in srgb, red 10%, blue)                 // [b & i] sum to 100%
color-mix(in srgb, red 50%,       blue 40%)          -serializes to-     color-mix(in srgb, red 50%, blue 40%)             // [b & j] only one is 50% (p1)
color-mix(in srgb, red 40%,       blue 50%)          -serializes to-     color-mix(in srgb, red 40%, blue 50%)             // [b & j] only one is 50% (p2)
color-mix(in srgb, red 30%,       blue 40%)          -serializes to-     color-mix(in srgb, red 30%, blue 40%)             // [b & j] sum to less than 100
color-mix(in srgb, red 75%,       blue 75%)          -serializes to-     color-mix(in srgb, red 75%, blue 75%)             // [b & j] sum to more than 100
color-mix(in srgb, red calc(10%), blue 50%)          -serializes to-     color-mix(in srgb, red calc(10%), blue 50%)       // [b & j] one is `calc()` (p1)
color-mix(in srgb, red 50%,       blue calc(10%))    -serializes to-     color-mix(in srgb, red 50%, blue calc(10%))       // [b & j] one is `calc()` (p2)
color-mix(in srgb, red calc(10%), blue calc(90%))    -serializes to-     color-mix(in srgb, red calc(10%), blue calc(90%)) // [b & j] both are `calc()`

color-mix(in srgb, red 50%,       blue)              -serializes to-     color-mix(in srgb, red, blue)                     // [c & k] only p1 specified, is 50%
color-mix(in srgb, red 10%,       blue)              -serializes to-     color-mix(in srgb, red 10%, blue)                 // [d & k] only p1 specified
color-mix(in srgb, red calc(50%), blue)              -serializes to-     color-mix(in srgb, red calc(50%), blue)           // [d & k] only p1 specified, is `calc()`

color-mix(in srgb, red,           blue 50%)          -serializes to-     color-mix(in srgb, red, blue)                     // [e & l] only p2 specified, is 50% 
color-mix(in srgb, red,           blue 90%)          -serializes to-     color-mix(in srgb, red 10%, blue)                 // [f & m] only p2 specified 
color-mix(in srgb, red,           blue calc(50%))    -serializes to-     color-mix(in srgb, red, blue calc(50%))           // [g & n] only p2 specified, is `calc()` 

color-mix(in srgb, red,           blue)              -serializes to-     color-mix(in srgb, red, blue)                     // [g & o] neither is specified
@weinig
Copy link
Author

weinig commented Aug 23, 2024

@svgeesus
Copy link
Contributor

Thanks @weinig both for the suggested wording and also especially for the set of worked examples!

@svgeesus svgeesus added the css-color-5 Color modification label Aug 28, 2024
@svgeesus svgeesus self-assigned this Aug 28, 2024
@svgeesus
Copy link
Contributor

The text states it should use the "un-normalized" values. The value of 60% would only be discovered during the normalization (specifically, step 4)).

This is true.

Because this section evolved over time, I think that my mental model was whether a number had changed, like color-mix(in oklab, red 75%, blue 150%) becoming 33.33% and 66.67% respectively; and I originally wrote that those modified values would be the ones serialized. But then there were problems, like knowing if they had originally added to less than 100%, so we went for the un-normalized wording without noticing that unspecified values only get a value during normalization.

Your suggested wording is much better.

@svgeesus
Copy link
Contributor

svgeesus commented Sep 2, 2024

@emilio @kbabbitt @nt1m are we good with these suggested changes? And if so we should be get a WG resolution.

@svgeesus
Copy link
Contributor

@emilio @kbabbitt @nt1m it would be great to get any concerns logged here, before TPAC, so that we can get a quick resolution to adopt the wording from @weinig and also get the examples into WPT tests.

@nt1m
Copy link
Member

nt1m commented Sep 16, 2024

I trust @weinig :)

@kbabbitt
Copy link
Contributor

@weinig @svgeesus

Thanks for the writeup and the ping. I looked at the proposed text and existing test cases in color-valid-color-mix-function.html. Am I understanding correctly that the changes would only clarify the existing behavior and not introduce any changes to expected serializations? If that's the case, I'm happy with the new wording.

If there are behavior changes in the wording that I missed, could you please point them out?

@svgeesus
Copy link
Contributor

svgeesus commented Sep 17, 2024

Am I understanding correctly that the changes would only clarify the existing behavior and not introduce any changes to expected serializations?

Exactly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Agenda+ css-color-5 Color modification
4 participants