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-4] Color modifications proposal: extending color functions #3187

Closed
LeaVerou opened this issue Oct 1, 2018 · 36 comments
Closed

Comments

@LeaVerou
Copy link
Member

LeaVerou commented Oct 1, 2018

Edit: Most current proposal here, just go straight there unless you want to read the thread for historical reasons.


The lack of a color modification syntax is one of the few things that authors still use preprocessors for, and severely limits what CSS variables can do. I'm going to post this proposal I've been thinking about for a while. It's by no means perfect, but perhaps it can get the discussion going, so we end up with something decent eventually!

Goals of a color modification syntax

  • Setting any color coordinates for all color functions, either to absolute values or to values relative to the modified color (e.g. set to 0.3 or increase by 50%)
  • Avoiding accidental gamut clipping. If a syntax converts to sRGB, it should be syntactically obvious that this is happening.
  • Easy lighter/darker variants (tint/shade)
  • Blending of two or more colors
  • Getting white or black depending on which one contrasts better with the base color

Proposal

This is loosely inspired from the current practice of defining major theme colors as color components in a variable (e.g. --color: 180, 60%) and then using them in color functions (e.g. hsl(var(--color), 90%)). However, this is simple textual substitution, which is insufficient, and imposes constraints on how the base color is defined.

I’m proposing to extend all color functions to allow for a <color> argument. If the color argument is present, it is converted to the target color space of the function, then the remaining arguments set or modify its coordinates in that color space. A _ or same keyword can be used to mean "no change". For example, if a function’s grammar is <number>{3}, it will become <color>? (<number> | _){3}.

For example, hsl(red _ _ 90%) would create an HSL color with a lightness of 90%, and the saturation and hue from the provided color.

Before any modification, the color would be converted to the target color space of the function used. This means that modifications using hsl() can be lossy (since the color would need to be converted to sRGB), but there is no such problem with lab() or lch(). However, any syntax that allows modifying HSL or RGB coordinates would have the same issue, at least this syntax makes the conversion more explicit.

Directly setting arguments is not sufficient for most modifications, since it cannot perform relative modifications (e.g. "increase L by 10%" instead of "set L to .3"), which are far more common use cases. Therefore, we need to introduce a syntax for relative modifications as well.

Ideas for that:

  • rel(<percentage>): Multiplies the color component by <percentage>. E.g. lab(red rel(60%) rel(100%) rel(100%)) would convert red to Lab, and then multiply its L by 60%.
  • up <percentage>/down <percentage>: Relative addition/subtraction. The previous example would be lab(red down 40% up 0% up 0%). Given the lack of commas that we recently introduced, I'm finding this hard to read, since the keywords are not visually grouped with their percentages.
  • Defining keywords for each coordinate, then using calc(). E.g. the previous example would be lab(red calc(.4 * l) a b). Seems the most expressive and flexible, but probably too messy to define.

With the syntax for relative modifications, this addresses most desired adjustments, and expands naturally with every new color function. Tint and shade could be relative modifications on hwb(), though adjusting the L of Lab/LCH is better as it's lossless (and produces fantastic results).

Benefits of this syntax

  • Extends on syntax that authors are already familiar with. No need to learn different ways to refer to the same color components.
  • Can be understood by anyone who understands the existing color functions, even if they are unaware that a modification syntax exists.
  • Makes the target color space very obvious, since it looks like creating a new color
  • Every new color function comes with new color adjusters for free, no need to learn anything new besides using the color function.

Drawbacks

  • Does not address contrasting colors
  • Does not address blending of two or more colors. Perhaps these could be defined as separate functions, maybe cross-fade(), since we need to address this for interpolation too?
  • It’s easy to clip the modified color to sRGB, since authors are very familiar with HSL and many would use that. However, any color adjustment syntax that supports adjusting hue, saturation, lightness would have the same issue. At least this syntax makes it obvious that you are creating an hsl() color, with the gamut limitations that this comes with.
  • Stupid lossy transformations can be defined, like color(hsl(color(mycmyk .1 .2 .3 .4) mycmyk 60%) .4). However, a) any sufficiently powerful syntax will allow for silly things, and b) see point above.
@LeaVerou LeaVerou added the css-color-4 Current Work label Oct 1, 2018
@birtles
Copy link
Contributor

birtles commented Oct 1, 2018

Thank you for doing this. I'd love to see this happen.

I'm curious about how to make this apply to the underlying value so that you can, for example, have a generic saturate class, or desaturate class for that matter. We could define a syntax that applies to the cascaded value something like font-size: larger does but that's a nightmare to implement (I suspect there are still plenty of animation edge cases here in particular) so I think we probably don't want to go that route. Perhaps we just need to define this in such a way that additive CSS will work, particularly now that we have definitions for how to add CSS values.

For example, with the current addition facilities for animation one can already bump up the green channel by adding rgb(0, 128, 0) to the underlying value but there's no facility for subtracting from a channel, nor operating on, say, the luminance channel.

@tabatkins
Copy link
Member

I like the re-use of the existing color functions for modifying the channels in-place. I wouldn't make any of the arguments optional, tho; that seems both unnecessary and confusing - your hsl(red 90%) example shows that off. It's not just a parsing problem, it's an understanding problem - to understand that, you need to recognize that 90% can't be the first value, so it must be the second value.

Instead, I think they should all be the same mandatory-ness as usual, and we use your same idea, or simplify it even more: hsl(red _ 90% _), with the _ ident indicating that you take that value from the provided color. (And when values can be omitted, like alpha, they default to _, I guess?).

@LeaVerou
Copy link
Member Author

LeaVerou commented Oct 3, 2018

Yeah, agreed. I guess then we need to find a syntax for same and relative values that is both sufficiently understandable and sufficiently terse. I’m a tiny bit worried that _ may be too terse, but mostly I think I like it.

One benefit of the optional argument syntax that is now lost is that it's also a color space conversion syntax. rgb(var(--mycolor)) clips to sRGB, color(var(--mycolor) myCMYK) would convert to CMYK. Not sure how useful that was by itself and whether we want to preserve it. It can still be expressed via rgb(var(--mycolor) _ _ _) and color(var(--mycolor) myCMYK _ _ _ _) respectively.

@birtles
Copy link
Contributor

birtles commented Oct 4, 2018

I was a bit concerned about how this overlaps with additive CSS―assuming that happens sometime in the near future.

On that one hand, additive CSS seems to provide something similar, i.e. presumably one could write border-color: hsl(0deg 50% -50%) !add and we'd define it so it combines with the underlying value by converting as necessary to HSL first (and similarly for Lab etc. too).

However, I think getting additive CSS to apply to a color in an arbitrary CSS variable is sufficiently awkward (you'd have to have a separate rule to make the underlying value use the CSS variable) that this proposal makes sense in its own right. This proposal is also a lot more elegant when altering the color component in a more complex value.

@Crissov
Copy link
Contributor

Crissov commented Oct 4, 2018

hsl(red 90%) would create an HSL color with a lightness of 90%, and the saturation and hue from the provided color. Potential flaw: In hsl(red 0% 50%): is the 0% saturation or lightness? We need to parse the next token to figure that out.

That is just like properties with optional values. We have all sorts of rules for which value is used to fill in missing ones. Iʼm not sure you are proposing the most intuitive one here. hsl(red 90%) could expand to any of the following, all using the hue from red:

  • hsl(red 90% 90% 90%) – this and similar ones would make more sense if hsl(0deg 90%) expanded to hsl(0deg 90% 90% 90%)
  • hsl(red 90% 90% red)
  • hsl(red 90% red 90%)
  • hsl(red red 90% 90%)
  • hsl(red 90% red red) – I believe this is the most systematic expansion
  • hsl(red red 90% red) – assumed in the original proposal above
  • hsl(red red red 90%)

With RGB, the single provided percentage value might even apply to the first, red channel.

@LeaVerou
Copy link
Member Author

LeaVerou commented Oct 4, 2018

Since Tab convinced me that optional arguments are a bad idea, I updated the original post so that it's not reflecting a proposal that even I don't support anymore, and so we can focus on the parts of the syntax that matter more.

@Crissov
Copy link
Contributor

Crissov commented Oct 4, 2018

🆗
With the keywords for coordinates idea, you would not need the underscore: hsl(red h s 90%). Single letters may actually work better than words because of rgb(red red green 90%).

@Martin-Pitt
Copy link

Martin-Pitt commented Oct 14, 2018

Had no idea that you can drop all the commas in those css functions. Wow, that feels weird and vague.

I like the idea of using single-letter keywords for placeholders as they match the functions' names. It creates a clear mapping. It only gets a bit weird when it comes to the alpha components on lab/lch as we don't have laba/lcha.

What about keywords and +/-?

hsl(h s 50% from red), set lightness to 50% from the color red
hsl(+20deg s l from green), rotate hue by +20deg from the color green
hsl(-15deg +10% -20% from lightblue), rotate hue by -15deg, add 10% saturation, subtract 20% lightness from the color lightblue

Or:

hsl(red to h s 30%), set red to lightness of 30%
hsl(darkblue to 0deg s +30%), set darkblue to hue of 0deg and add 30% lightness

I realise it might get confusing/conflict with absolute negative values. I think hsl can have negative hue values.

Perhaps there are ways to lean on calc instead as that is meant for number tweaking? Given the placeholders:

hsl(calc(h + 5deg) calc(s + 10%) calc(l - 10%) from darkbrown)
hsl(calc(h - 20deg) s l from blue)

Testing longer keywords again:
hsl(calc(hue + 5deg) calc(saturation + 10%) calc(lightness - 10%) from darkbrown)

I kind of like using calc for relative tweaking now that I think about it.

hsl(h calc(s * 2 - var(--prop, 50%)) l from darkred)

@LeaVerou
Copy link
Member Author

LeaVerou commented Oct 14, 2018

While keywords usually increase readability, in this case since there are no commas to group the different arguments. Therefore, keywords like from or to read like a separate argument, and don't look grouped with anything.

Using + and - to indicate relative modifications would indeed be the most readable, but unfortunately, it's not an option for disambiguation reasons. The parser sees +10% and 10% as equivalent.

I love the idea of using calc() for tweaking! It would even work with the generic _ we were discussing above. It would be the first case of using keywords in calc(), which may make it trickier to implement, but hopefully the flexibility is worth it? After all, we were always planning to use keywords in calc() eventually.

@AmeliaBR
Copy link
Contributor

I like the idea of working with the syntax we've got, although complicating the arguments of the color functions is starting to make dropping the commas look like a bad idea.

There definitely needs to be some sort of grouping structure, even if it's just a mandatory wrapping () without a calc prefix, so that you can distinguish addition /subtraction from simply setting the next number in the sequence. And distinguish division from the new syntax of using / to separate the alpha channel.

I find the use of the component initials as the placeholder for the starting value more intuitive & easier to read than _. But I recognize that there are long-term benefits to having a single token that works in any colour function, especially when you consider custom color systems. But maybe it could be both? The definitive syntax could use a generic placeholder, but allow the letters a synonyms in the common functions?

I like the idea of using a from <color> keyword approach, especially when you consider that the color would often be a variable, and some of the parameters may also be variables, so an extra keyword would help in readability.

So, what I'm thinking of is something like this:

rgb(from var(--backdrop), r g b/0.5) /* this is making alpha=0.5, not changing the blueness!*/
hsl(from var(--accent), h (s/2) (l - 20%))
lab(from var(--primary), var(--luminance) a b)

Re @birtles musing about an additive mode: we could define it so that the relative adjustments are valid without the from <color>, bit. The color could default to transparent black, but in additive mode it could be whatever the base color in the adjustment stack is.

@tabatkins
Copy link
Member

although complicating the arguments of the color functions is starting to make dropping the commas look like a bad idea.

If one only needs the commas to put potentially-clashing complex grammars together, that suggests one should be using functions to contain the grammars instead; as an added bonus, you can then use commas in the function without clashing with the channel separator.

As an added bonus, functions give names to the functionality, which makes them easier to recognize and search for.

@AmeliaBR
Copy link
Contributor

that suggests one should be using functions to contain the grammars instead

Yeah, I kind of acknowledged that in my next sentence. It was just getting difficult to mentally parse some of the examples people were presenting earlier in the thread. I was sort of cheating by using brackets without a function name, but I agree with

functions give names to the functionality, which makes them easier to recognize and search for.

That said, I'm concerned about reusing calc() if we're also going to add a context-specific token. So my vote would be for rel() or adjust() or something like that. But I still like the idea of having a token for the current variable, to clearly distinguish rel(s + 20%) from rel(s*20%).

@LeaVerou
Copy link
Member Author

I agree that named components are far more intuitive, I'm just not sure what happens in the case of color() and custom color profiles. I wonder if we can allow people to provide letters for the components in the @icc-profile rule (or whatever it's called) and default to a, b, c, d, ... otherwise?

@tabatkins
Copy link
Member

Note an issue with single-letter names: lab() has both an "a" component and an alpha.

@AmeliaBR
Copy link
Contributor

Note an issue with single-letter names: lab() has both an "a" component and an alpha.

That's not really an issue if resolution of the token is always based on the position in the function. It's only an issue if we allow parameters to be omitted in the middle or if we allow complex color-matrix type math. The rel() function could be defined to take any <custom-ident> token, and that ident would always resolve to the underlying value of that component in the base color.

@AmeliaBR
Copy link
Contributor

One benefit of the optional argument syntax that is now lost is that it's also a color space conversion syntax. rgb(var(--mycolor)) clips to sRGB,

I don't think that should be true. The color functions allow out-of-gamut parameters; this is especially necessary since computed color values are always converted to rgba() format. Clipping only happens to device limitations at used value time.

But that makes me thinking that in addition to a relative adjustment function, there should maybe be a clamp() function (or separate max/min functions) that can use the underlying value as starting point.

@LeaVerou
Copy link
Member Author

LeaVerou commented Oct 15, 2018

@AmeliaBR All existing color functions are defined as operating in sRGB, e.g. look here for rgb(). rgb(100%, 0, 0) is not the brightest red the monitor can produce, it's the brightest red in sRGB. Out of range values are indeed allowed, but the resulting color is always in sRGB.
And yes, this does mean that until browsers implement lab() and lch(), we can't use the brightest colors in today's monitors with CSS.
And no, making rgb() device-dependent is not the way to go.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Oct 15, 2018

@LeaVerou from a later paragraph in that section:

Values outside the device gamut should be clipped or mapped into the gamut when the gamut is known: the red, green, and blue values must be changed to fall within the range supported by the device.

So per spec, clamping applies to the device gamut, not the sRGB gamut. Not sure whether or not that's implemented: you'd have to test whether rgb(150%, 0%, 0%) on wide-gamut devices is noticeably brighter than regular red.

@svgeesus
Copy link
Contributor

So per spec, clamping applies to the device gamut, not the sRGB gamut.

Yes, but in the proposed syntax, functions which operate on sRGB values will necessarily also involve a clip of the intermediate values to sRGB if the color you are modifying from is outside sRGB. In practice, that is easily avoided but the spec has to state what happens with all possible combinations, not just sensible combinations.

Not sure whether or not that's implemented

It is impossible to not implement it :) a device can't display colors outside it's gamut, by definition.

@LeaVerou
Copy link
Member Author

I was under the impression that rgb(400, 0, 0) is first clipped to rgb(255, 0, 0) and then that might be further clipped if the device gamut is smaller than sRGB (which was common when CSS Color 3 was authored, e.g. the 2013 MacBook Air gamut is around 62% of sRGB, and that's not super long ago!). This seems to be on par with what Chrome and Safari are doing (test), while Gecko erroneously treats colors as being specified in device RGB and not sRGB (it still clips to 255, but in this case the opposite would be outside the device gamut).

@wbond
Copy link

wbond commented Nov 19, 2018

Sublime Text's minihtml engine had the need for color modifications last year, and I implemented them using the older draft of the color-mod function. Rather than invent our own syntax, it seemed to make sense to start from a foundation that had been previously discussed. Not all aspects of that have been implemented, but recently I ran into a use case that feels worth considering since this new proposal is being discussed.

We have two components of the UI that introduce color - the theme and the color scheme. The color scheme includes colors fo syntax highlighting, and the theme controls the editor chrome. Color schemes are relatively easy to create and include diverse palettes. Themes require much more work, including raster graphics. Because of this, themes can derive colors from the color scheme.

This introduces the issue of ensuring contrast. The original contrast() modifier only allowed modifying a color to create a new color the was appropriately contrasted with the base. This may be useful in some situations, but in our use case the issue is tweaking a color so it is appropriately contrasted with a different base. For instance, a blue color from a color scheme needing to be high enough contrast to be used as foreground on a grey background.

So in addition to:

Getting white or black depending on which one contrasts better with the base color

It seems it would be nice to have an option for:

  • Modifying a color to meet a luminosity ratio, when compared to a second color

Hard-coding the ratio to 4.5 and then allowing blends between that and the maximum contrast color seems less useful than the user being able to specify the minimum contrast they want. It may not be that 4.5 is required (such as for headlines), or that the UI element is a decoration that requires some contrast, but not a full 4.5.

It seems most of the discussion on syntax so far has been for modifying components of a color in a specific color space. (My personal take on that is that the rel(50%) syntax feels like one of the less complicated syntactic approaches.) So the following example is not endorsing a specific syntax, but proposing a basic concept that would be useful.

color-contrast(var(--red) var(--bg) 3.0)

This would modify the var(--red) to have a contrast ratio of at least 3.0 when compared with var(--bg). I would be fine with the syntax being contrast(), min-contrast() or contrast-adjust().

If there was a function to pick color based on contrast, perhaps something like pick-contrast(white black var(--bg)). There is also the idea proposed in #1627 of picking the closest contrasting color from a list and then adjusting it to meet the required contrast ratio.

In terms of blending, cross-fade() makes me think of audio production, as opposed to colors. I think blend() or lerp() may be a better fit for the color domain.

@LeaVerou
Copy link
Member Author

LeaVerou commented Jun 5, 2019

I figured I'd make some edits to the original proposal that reflect the discussion so far, and my take on the issues raised.


Proposal

This is loosely inspired from the current practice of defining major theme colors as color components in a variable (e.g. --color: 180, 60%) and then using them in color functions (e.g. hsl(var(--color), 90%)). However, this is simple textual substitution, which is insufficient, and imposes constraints on how the base color is defined.

I’m proposing to extend all color functions to allow for a <color> argument, preceded by the keyword from to make it clear that this is a color (in case a variable is used). If the color argument is present, it is first converted to the target color space of the function, then its coordinates are adjusted based on the remaining arguments. A _ keyword represents the value of each coordinate and can be used by itself to mean "no change", or in calc() for relative modifications.

Edit: As of the June 5 F2F discussion, we are not going to use _ but keywords or letters. How we handle color() is yet to be decided. I'm gonna use a, b, c etc in the examples below for now.

Before any modification, the color would be converted to the target color space of the function used. This means that modifications using hsl() can be lossy (since the color would need to be converted to sRGB), but there is no such problem with lab() or lch(). However, any syntax that allows modifying HSL or RGB coordinates would have the same issue, at least this syntax makes the conversion more explicit.

With the syntax for relative modifications, this addresses most desired adjustments, and expands naturally with every new color function. Tint and shade could be relative modifications on hwb(), though adjusting the L of Lab/LCH is better as it's lossless (and produces fantastic results).

Examples

  • lch(from var(--accent1), calc(l * 1.2) c h) would adjust var(--accent) to be a little lighter.
  • lch(from var(--accent1), calc(l + 10) 230 h) would adjust var(--accent) to be very bright (sets its Chroma to 230) and slightly increase its lightness (add 10 to it).
  • rgb(from indianred, 255 g b) would produce the same color as indianred but with 255 in the red channel. The result would be in sRGB since that's what the rgb() function produces.
  • color(from var(--main), myCmyk calc(a * 1.2) b c d) produces a CMYK color (in a custom CMYK color space) with its Cyan channel increased.
  • lab(from var(--mycolor), l a b / 40%) sets the alpha of var(--mycolor) to 40% regardless of what it originally was (and no gamut clipping occurs since lab() encompasses all visible color).

Benefits of this syntax

  • Color spaces are an intrinsic part and not an afterthought.
  • Extends on syntax that authors are already familiar with (existing color functions and calc()). No need to learn different ways to refer to the same color components.
  • Can be understood by anyone who understands the existing color functions, even if they are unaware that a modification syntax exists.
  • Makes the target color space very obvious, since it looks like creating a new color.
  • Every new color function comes with new color adjusters for free, no need to learn anything new besides using the color function.
  • Supports both relative and absolute adjustment, and relative could be either additive (e.g. "add 10% to lightness") or multiplicative (e.g. "multiply lightness by 120%"), or even a combination of both, since it can utilize the entire power of calc().

Drawbacks

  • Gives authors too much rope to hang themselves with: Most will resort to hsl() modifications because that's what they're familiar with, even though lch() produces better results and takes maximum advantage of the device gamut. It’s easy to clip the modified color to sRGB, since authors are very familiar with HSL and many would use that. However, any color adjustment syntax that supports adjusting hue, saturation, lightness would have the same issue. At least this syntax makes it obvious that you are creating an hsl() color, with the gamut limitations that this comes with.
  • Might be too complex. Do we really need adjustment of every possible color channel in every color space, or would it be sufficient to just use L, C, H and cover the main use cases?
  • Does not address contrasting colors or blending of two or more colors, these could need to be done via separate functions.

@una
Copy link
Contributor

una commented Jun 5, 2019

Another idea for implementation: https://gist.github.com/una/edcfa0d3600e0b89b2ebf266bf549721

@css-meeting-bot
Copy link
Member

The CSS Working Group just discussed Color Stuff, and agreed to the following:

  • RESOLVED: Put all the proposals into css-color-5, ChrisL and future Una as editors
  • RESOLVED: Rename to put 'color' first, adjust-color -> color-mod()
  • RESOLVED: Add color-contrast() without currentbg
  • RESOLVED: Add color-mix(), try to align with cross-fade()
  • RESOLVED: Put both color adjustment proposals into css-color-5, with keywords instead of css-color-5
  • RESOLVED: Add Lea Verou as editor of css-color-5
The full IRC log of that discussion <fantasai> Topic: Color Stuff
<AmeliaBR> s/Color Stuff/Color modification functions/
<chris> github: https://github.com//issues/3187
<fantasai> una: Chatting with TabAtkins and my team about color modification b/c very highly requested
<fantasai> una: Used a lot in preprocessors
<AmeliaBR> Una's proposal: https://gist.github.com/una/edcfa0d3600e0b89b2ebf266bf549721
<fantasai> una: Very common pattern, so wanted to revisit as native CSS
<fantasai> una: Here's a proposal for a more simplified proposal
<fantasai> una: based on three functions
<fantasai> una: adjust-color(), mix-color(), and contrast-color()
<fantasai> una: color adjustment is basic modification via hcl values
<fantasai> una: first arg is color to adjust, then list of modification functions
<fantasai> una: mix-color mixes two colors
<fantasai> una: contrast-color, submit a bgcolor and then list of color values
<fantasai> una: that you would place as text and background, and picks the highest contrasted color
<fantasai> una: HCL would be default color space
<fantasai> una: can also have color space argument
<fantasai> una: lightness in LCH vs HSL
<fantasai> una: If using lightness in a color space in e.g. cmyk, then do transformation in LCH and then clipped to CMYK range
<fantasai> una: Wanted to make easy to use
<fantasai> chris: Like picking LCH by default because it ... gamut
<fantasai> chris: result will always be a color
<fantasai> chris: like that it's explicit about color space
<fantasai> chris: Does mix up in what color space doing calc and what you revert to
<fantasai> chris: Gave some comments on this
<fantasai> chris: slightly concerned that ppl will believe that lightness = bright ness and chroma = saturation
<fantasai> chris: Need to understand that ...
<fantasai> chris: Like that we have mixing colors, pretty convenient
<fantasai> chris: I do this often by putting colors on a gradient to find a color in between
<fantasai> chris: Unsure about ...
<fantasai> chris: Contrast color, I like that. Saw ppl asking for conrast things
<fantasai> chris: But often they're asking for ...
<fantasai> chris: Finding most contrasty color is nice
<fantasai> chris: ....
<fantasai> chris: I do like the idea of having a thing called currentBackground that we can use elsewhere
<fantasai> chris: Lea points out that once you have opacity, you have ranges of contrasts
<tantek> currentbgcolor
<astearns> s/unsure about .../unsure about mixing by component/
<fantasai> leaverou: What do you do about ranges that are overlapping?
<fantasai> una: Transparency issue is still unsolved by dev tools and a11y
<fantasai> una: so don't know how best to handle that
<fantasai> una: but still creating contrast checkers in devtools and other things, can re-use technology
<fantasai> una: pick best color
<fantasai> una: up to author to make sure it contrasts enough
<fantasai> leaverou: not deal breaker, many ways to specify
<fantasai> leaverou: just something that needs to be addressed
<AmeliaBR> s/asking for .../asking for the ability to tweak their preferred color to meet minimum contrast requirements/
<fantasai> una: background with rgba have a difficulty
<fantasai> leaverou: can also have semitransparent text, though
<heycam> q+
<fantasai> chris: I think it's an interesting proposal
<fantasai> chris: lots of details to tweak, but overall it's nice
<Rossen_> q?
<fantasai> chris: also clamping needs to be defined
<fremy> q+
<fantasai> chris: ...
<fantasai> una: I think we could .. with filter now, brightness/saturation
<fantasai> una: I like unclamped
<fantasai> una: can use value of 1000
<fantasai> una: creates interesting effects in CSS that wouldn't otherwise be possible
<fantasai> chris: Clamping should be done at last possible moment
<chris> q?
<fantasai> leaverou: Let's discuss other proposal too so that we can compare. Might end up with blend of both
<astearns> ack heycam
<fantasai> heycam: overall I like the idaea of color adjustment things
<fantasai> heycam: one comment about syntax for mix-color, for images we have the cross-fade function
<fantasai> heycam: so if we only want one axis of interpolation, should aign the syntax wth that
<fantasai> heycam: this kind of liear interpolation is something ppl want for other numeric tpes as well
<fantasai> heycam: e.g. interpolation of lenghts
<fantasai> heycam: so maybe generic way for different types, or separate thing for color
<fantasai> TabAtkins: We have outstanding rsolution for generic interpolate() function
<fantasai> TabAtkins: but mix-color can do more than simple interpolate
<fantasai> TabAtkins: mix-color can mix different aspects of the color, pay attention to opacity or not, so much more complicated than other tpes
<fantasai> AmeliaBR: For mix-color, heycam talking about cmparison with cross-fade
<fantasai> AmeliaBR: A comparison I think of is blend-modes
<fantasai> AmeliaBR: The efault mixture of two colors is equivalent ot normal blend more
<fantasai> AmeliaBR: to exten there's a % adjustment, that's adjusting opacity of the top blend layer
<fantasai> AmeliaBR: Instead of talking about blending two colors using certian channels, maybe mixing using different blend modes is a way to go
<fantasai> AmeliaBR: But general rule is re-use existing concepts in CSS as much as possible
<fantasai> una: really like idea of thinking as blend modes
<fantasai> una: agree that re-using concepts can be nice here
<astearns> ack fremy
<chris> s/asking for .../asking for a 4.5:1 ratio to pass WCAG/
<fantasai> fremy: I was wondering about the color-conrast function
<fantasai> fremy: mainly I'm trying to understand how to use in application
<fantasai> una: Used for a11y if you have reusable elements
<fantasai> una: or dark mode
<fantasai> una: if you switch from light pink bg to dark purple bg
<fantasai> una: need to ensure conrast
<fantasai> una: only have to specify colors one time
<fantasai> una: it'll update the color on top of the background
<fantasai> una: common thing from SASS that ppl love
<fantasai> TabAtkins: crude example here: text is black or white depending on bg in this color palette
<fantasai> leaverou: use case right there on github with labels, can give your labels custom bg colors, and GH picks text color to contrast sufficiently -- automatically do that with contrast-color()
<fantasai> fremy: Now I understand the use case, label use case is very clear
<fantasai> AmeliaBR: One thing about the way una describe diferent from conrast function previously
<fantasai> AmeliaBR: previous contrast function, you gave a fixed color and a 2nd color and then a desired contrast ratio
<fantasai> AmeliaBR: and it adjusted 2nd color to meet the contrast ratio
<fantasai> AmeliaBR: As I understand deciding the correct math for that wasn't satisfactory
<fantasai> AmeliaBR: Una's proposal the website author has to give a palette list
<fantasai> AmeliaBR: would just select best contrast from list instead of calculating adjustments
<fantasai> AmeliaBR: could default to black/white
<fantasai> chris: Advantage is end up with a color provided by author rather than random color
<fantasai> leaverou presents alternate proposal
<una> https://github.com//issues/3187#issuecomment-499126198
<leaverou> https://github.com//issues/3187#issuecomment-499126198
<fantasai> leaverou: this is just about color adjustment
<fantasai> leaverou: problem with color-mod was it only worked in rgb
<fantasai> leaverou: Nowadays ppl use ? gamma monitors
<AmeliaBR> s/? gamma/wide gamut/
<fantasai> leaverou: ppl use terrible hacks by putting things into different variables and stringing together and stuff
<fantasai> leaverou: They've used ? in PostCSS, implemented in custom scripts, etc.
<fantasai> leaverou: Really need to settle on something whether this or Una's proposal
<fantasai> leaverou: THis proposal is based on fact that we have a number of color functions
<astearns> s/used ?/used color-mod()/
<fantasai> leaverou: besides rgb() and hsl(), also have lab() and ?
<AmeliaBR> +100 to we need color modification functions (of some syntax)!!!
<fantasai> leaverou: Every color adjustment can be described as djusting channels on one of those functions
<fantasai> leaverou: Instead of creating colors, augment by introducing a coor argument on each of them
<fantasai> leaverou: so either set coordinates specifically or use calc()
<fantasai> leaverou: could also use an underscore to say that this component stays the same
<fantasai> leaverou: so making lighter, use lch, multiply lightness by 1.2 would make it lighter
<fantasai> leaverou: benefit of this is that every color function gives us extra djusters for free
<fantasai> leaverou: Easy to understand b/c uses existing color functions
<fantasai> leaverou: Let's say you have cmyk() space, comes with its own adjusters
<fantasai> leaverou: also allows adjusting alpha
<fantasai> leaverou: re-uses existing syntax, the adjustment just uses calc()
<fantasai> leaverou: obivous what the math is
<fantasai> leaverou: Drawback is that it might give authors too much rope
<fantasai> leaverou: they might just use hsl because familiar
<fantasai> leaverou: Una's proposal uses lch(), which does the right thing by default
<fantasai> leaverou: but worries me, e.g. doesn't have alpha
<fantasai> leaverou: what more is it missing, that we need to add?
<fantasai> leaverou: if we add 10 different keywords, then gets too big
<fantasai> leaverou: the only benefit is very clear what the target color space is
<fantasai> leaverou: Obvious when you convert colors
<fantasai> leaverou: clear what's going on
<fantasai> leaverou: but it's also more complex
<fantasai> leaverou: clarity comes at a cost
<fantasai> chris: I like being explicit about the color space of computation and result
<fantasai> chris: converting from starting not hard
<fantasai> chris: _ is awkward, but might be familiar to ppl using SASS etc, where they construct the result bit by bit
<fantasai> chris: Also like using calc()
<fantasai> chris: You could do all sorts of interesting things with calc(), so that's astrength
<fantasai> chris: if we do get on to cmyk and 7-color printing, hexachrome
<fantasai> chris: we don't have to invent new things
<fantasai> chris: we just get them for free because it's whatever position it is in the synta already
<fantasai> chris: but...
<fantasai> chris: Una's proposal does 3 things and each function
<fantasai> chris: Your proposal does only one thing, doesn't do the other two
<fantasai> chris: The color functions become extremely complicated syntactically
<fantasai> chris: First thought was I didn't like this because looked complicated
<fantasai> chris: I would like to dive more into what serialization is
<fantasai> chris: in general need to understand what serialization is and what's stored in DOM
<fantasai> chris: Right now colors are stored as sRGB and that's it
<fantasai> chris: Everyone that's seen the color spec, yeah this is good, have LCH and ICC colors
<fantasai> chris: high dynamic range etc. solved problem, doing this the right way
<fantasai> chris: But interested in how browsers are going to add this
<fantasai> chris: So would like to hear comments from implementers
<fantasai> chris: Both of these also depend on existing color functions, so need implementers to comment on that too
<fantasai> leaverou: both of these would require implementation of LCH
<fantasai> AmeliaBR: Do any browsers have work on the way to implement more advanced color spaces?
<fantasai> TabAtkins: Don't have work on it, but also LCH is only matrix-math different from sRGB, so not hard, just need some engineering time
<fantasai> chris: All the matrix math is in the spec
<fantasai> chris: also don't have to implement it like that, can also use ICC or color sync
<fantasai> chris: does all that as well
<fantasai> AmeliaBR: Lea's syntax can be implemented in parallell, since still get adjustments on rgb and hcl, just that the best artistic results come from lab or lch
<fantasai> leaverou: If HSL adjuster is implemented first and then LCH later, then more likely that existing designers will use HSL even though it's not as good
<fantasai> fremy: well it works for them
<fantasai> chris: It works for them because it's the only tool they have
<fantasai> TabAtkins: If you have boht, there's no reason to use HSL, LCH is wayyyy better
<fantasai> TabAtkins: Only reason to include older worse ones is compatibility with existing color systems
<fantasai> TabAtkins: but want to make using the good function the easy pasth
<myles_> q+
<fantasai> TabAtkins: so ppl use it and get happy results
<fremy> (to correct the notes, I just said that if designers end up using it, that means it worked for them, if the result isn't good enough, they can learn how to improve)
<fantasai> una: Problem with Lea's proposal is harder to understand what's going on
<fantasai> una: Harder to follow what's happening
<fantasai> una: Taking concepts of ?, transformation space, and output clipping
<fantasai> una: then build on that
<fantasai> leaverou: That's what I was wondering about as well
<fantasai> leaverou: ? lightness and hue cover a large percentage of cases. Unsure about individual color channels
<fantasai> leaverou: SASS has these, wondering if we can get usage stats
<fantasai> leaverou: See how many ppl need them and what use cases are
<una> s/concepts of ?/concepts of color space transform + set clipping space
<fantasai> leaverou: most use cases I've come across are saturation and lighness
<una> s / concepts of ?/concepts of color space transform + set clipping space /
<astearns> ack myles_
<fantasai> chris: Making a color "more green" is a bit straightforward in rgb, but going towards blue-gree... makes more sense to give a target color and go closer to that
<fantasai> chris: Myles, you're building on top of ColorSync, would be interested in what would be hard to do easy to do etc.
<fantasai> myles_: not prepared to answer that
<fantasai> leaverou: Issue with 2nd one beign underscores, could be some keyword or whatever.
<fantasai> leaverou: was an underscore only beause avoids conflicts within color function
<fantasai> astearns: Anyone from implementers with enough color experience?
<fantasai> AmeliaBR: Reminder that use cases for color modicifcation is increasing steadily
<fantasai> AmeliaBR: FIrst with custom properties
<fantasai> AmeliaBR: You can't do it in the preprocessor, has to be in the browser to work with dynamic colors
<fantasai> AmeliaBR: going into dark mode and using system colors, don't have concrete color to manipulate
<fantasai> AmeliaBR: need to do dynamically in the browser
<fantasai> una: contrast-color important for dark mode especially
<fantasai> una: these work hand in hand with changing technology being implemented in browsers now
<fantasai> heycam: One other syntax comment -
<fantasai> heycam: In 1st proposal, have adjust-color(), but we have a color-adjust property...
<fantasai> AmeliaBR: Could go back to color-mod()
<fantasai> TabAtkins: Also switch it to color-mix()
<fantasai> ?: And color-contrast() to match
<fantasai> astearns: Comment about Una's proposal requiring LCH ...
<fantasai> astearns: ...
<AmeliaBR> s/?/heycam/
<fantasai> astearns: Want to reserve the default for LCH, require a color space until LCH is around, then allow that to be dropped
<fantasai> TabAtkins: I object
<fantasai> TabAtkins: I don't think the LCH part is the engineering blocker
<fantasai> TabAtkins: They're both relatively easy thing that just need effrot
<fantasai> TabAtkins: getting it right the first time
<fantasai> TabAtkins: if someone wants to impelment adjust-color(), then doing LCH also isn't hard
<fantasai> dbaron: Implementing color modification functions seems significantly mroe work than implementing LCH
<fantasai> markus: ... Adjustment of image color
<myles> q+
<fantasai> chris: Ther'es a longrunning FF bug about ICC and imgaes, maybe just for raster images?
<fantasai> Markus: ? is working on image color adjustment
<fantasai> TabAtkins: Handling profiles but not anything else... so outputting rgb as monitor color space?
<fantasai> chris: Can see the difference on my screen, Chrome really gives you the desaturation , Firefox ...
<fantasai> heycam: Since we don't color adjust CSS colors, which aspects of these proposals would not be possible ?
<fantasai> TabAtkins: none, just do the math
<fantasai> TabAtkins: If you have badly-adjusted colors mixed with other colors
<fantasai> TabAtkins: In a consistent color space, get better colors later
<fantasai> Markus: Nothing hard in the spec from my perspective
<fantasai> markus: Hard part is Firefox doing color management in the first place
<TabAtkins> s/mixed with other colors/mixed with other colors, you have a problem, but/
<fantasai> markus: I don't know about parsing / serialization, but in terms of spec hard part is just finding the right syntax
<fantasai> AmeliaBR: Rendering resulting color is a separate, but result of these functions is going to be another oclor function using exisitng color function syntax
<fantasai> AmeliaBR: question of what do we do about Browsers trying to squish color functiosn into hex codes when requesting coptued style
<fantasai> AmeliaBR: but that's an issue with all advanced gamut
<fantasai> chris: It's even an issue with sRGB
<AmeliaBR> s/gamut/gamut color functions/
<fantasai> chris: If you go into wide gamut or high gamut, not enough storag
<chris> q?
<AmeliaBR> s/storag/storage/
<chris> ack myles
<mstange> q+
<fantasai> leaverou: Tab, you said that colors mixed being in same color space... do you mena can't mix colors from different spaces?
<fantasai> TabAtkins: When mixing colors from differnet spaces and no color managing
<fantasai> TabAtkins: Then colors that look like they match won't later once you fix
<fantasai> TabAtkins: but if define the mixing color space then it's OK
<fantasai> AmeliaBR: If you have an imge that uses a color properly calibrated red
<fantasai> AmeliaBR: andyou have an uncalibrated red in your CSS, then your color scheme will look bad
<fantasai> TabAtkins: Used to be that RGB 255,0,0 in an image could look dfferent from red in CSS
<fantasai> dbaron: depending on whether image had color profiel data
<fantasai> una: You can mix colors from different spaces, have to speicfy mixing color space
<fantasai> leaverou: Would be nice to have defaults so that you don't have to speficy if you don't want to
<fantasai> leaverou: e.g. default to LAB
<fantasai> leaverou: if they're not in the same space
<fantasai> TabAtkins: One aspect of mixing proposal is nice to mix a single channel
<fantasai> TabAtkins: NOt directly interpolation
<fantasai> chris: That is an advantage of Una's proposal
<fantasai> chris: You could have a profoto RGB color and an adobe RGB color and ????
<TabAtkins> s/????/mix the lightness of them, which neither color space has/
<fantasai> myles: In first propsoal, contrast-color is different from first two otpions
<fantasai> myles: contrast-coor might be unimplementable depending on composting and how far back you have to go back through to find the bg color
<fantasai> myles: and if you don't punch through, kinda useless
<fantasai> TabAtkins: I don't think punching layers is good, problematic for implementations
<fantasai> TabAtkins: have to be in a reasonable situation like bg color on your element
<fantasai> myles: but is it good enough?
<fantasai> una: could require the first argument to be a solid color
<fantasai> dbaron: what is the computed value if you do this contrast color thing?
<fantasai> una: result would be a color
<fantasai> dbaron: in terms of CSS computed value, how is contrast-color going to inherit?
<fantasai> chris: I think the computed value would be the winning color
<fantasai> TabAtkins: It's a good question, need to figure that out
<astearns> q?
<fantasai> AmeliaBR: Question of how we dealt with currentColor -- it inherts as a keyword, and also wanted to switch the system colors to do that also
<fantasai> AmeliaBR: If we do that, then it would be awkward if the contrast selection is set at the body level but the actual element using that color has now the value of that varable or keyword ahs a different value
<fantasai> chris: If computed value is as specified ...
<fantasai> leaverou: Might not want a different alue on the child
<fantasai> dbaron: Part of my concern here is that except for this thing, it seems like the computed value can be computed to a color
<leaverou> s/Might not want a different alue on the child/even if it's a CSS variable, it could have a different value on the child/
<fantasai> dbaron: but this is the one thing in all this color adjustment stuff thats "layout"-dependent thing
<fantasai> TabAtkins: I don't think so... but if one of the options s currentColor or currentbg or whatever, then it's an issue
<chris> q?
<fantasai> fantasai: Systme colors also vary by element
<fantasai> dbaron: when you're doing style computation, you know what hte coptued value of the color property is. So you can know what currentcolor is as a color
<fantasai> AmeliaBR: we choose to inherit it as a keyword rather than a color
<fantasai> dbaron: Same for system colors. You can do the lookup
<fantasai> TabAtkins: Then I don't understand why other color mods are different
<fantasai> dbaron: I think all of that can happen in computed value
<chris> https://github.com/jonathantneal/postcss-color-mod-function
<fantasai> dbaron: The question is, is this definition of "aht is the relevant bg to contrast with", what does it depend on and is it something that can be resolved at computed value time locally?
<fantasai> dbaron: Or do you need to do layout to find out?
<fantasai> TabAtkins: Just being able to contrast with element's own background woudl be enough
<fantasai> AmeliaBR: I think it's better to leave out idea of "current background" rather than having overly-simplistic definition
<fantasai> AmeliaBR++
<fantasai> una: ...
<fantasai> una: You don't need it
<fantasai> emilio: You can use -webkit-text-fill-color
<AmeliaBR> s/.../we can leave out current background for now/
<fantasai> chris: If syntax is you put two colors in here, then new keyword
<fantasai> myles: I brought up contrast-color in order to differentiate from other functions
<fantasai> myles: picking between proposal A and B, contrast-color is distinct from either
<fantasai> myles: Ignoring it for the moment
<una> s/need it/need it because you can put currentColor in that slot and specify the background behind currentColor/
<fantasai> myles: Both of these proposals are saying here's some syntax, take the color, do some math in a coor space, and then put it back into a color space
<fantasai> myles: But do designers think in that terms?
<fantasai> myles: Amelia said about blend modes
<AmeliaBR> q?
<fantasai> myles: Instead of describing as channels independently, maybe match ? maybe match better how designer would think about it
<fantasai> AmeliaBR: I don't think they're opposing concepts
<fantasai> AmeliaBR: I think Una's proposal had an adjust color and a mix color
<fantasai> AmeliaBR: I'm suggesting an adjust color using oneof these syntaxes
<fantasai> AmeliaBR: And a blend color
<fantasai> AmeliaBR: Adjust color is lighten or brighten or dullen
<leaverou> q+
<fantasai> AmeliaBR: Mix is for ppl thining more of combinin two colors
<fantasai> AmeliaBR: You can interpret lighten / darken as combine with white/black
<florian> q?
<fantasai> AmeliaBR: but ...
<fantasai> leaverou: Wrt proposal A and B
<fantasai> leaverou: ? doesn't have mix color or contrast color
<fantasai> leaverou: so it's really about picking how to do the adjustments
<fantasai> leaverou: lighter / darker / more opaque / more translucent / etc
<AmeliaBR> s/.../you can't make saturation brighter or duller that way/
<AmeliaBR> s/?/my proposal/
<fantasai> TabAtkins: We have strong existence proof that ppl do think about this in terms of color adjusters, because every preprocess has a variant of channel adjusters
<fantasai> TabAtkins: might not be ideal, but super common
<fantasai> leaverou: Wrt blending modes
<fantasai> leaverou: My experience is that designers how blending modes work
<astearns> +1 leaverou
<fantasai> leaverou: Every time I give a talk about them
<astearns> s/designers how/designers don't know how/
<fantasai> leaverou: ppl come up to me, I didn't understand how these work, just tried different ones to see the result
<fantasai> una: ...
<fantasai> una: You can also clikc around in devtools to see what works for you
<fantasai> una: A huge use case for color funcitons is to create palettes from a single source
<fantasai> una: so you'll still need color adjustment and not just mixing
<fantasai> mstange: Two existing ways to mix colors
<fantasai> mstange: gradients
<fantasai> mstange: and transitions
<astearns> ack mstange
<fantasai> mstange: Is the ? color function equivalent to what those do?
<fantasai> mstange: or is that something we want?
<fantasai> TabAtkins: we should offer one
<fantasai> TabAtkins:both of those interpolate in premultipled sRGB space
<fantasai> TabAtkins: not idea space
<fantasai> TabAtkins: but good to provide that so can match
<fantasai> una: could remove arugments of whcih manipulations, and then mix those two colors evenly by default in sRGB
<fantasai> AmeliaBR: Agree that if we have a default it should match default for gradients and tansitions
<leaverou> s/My experience is that designers how blending modes work/My experience is that designers don't really understand how blending modes work, they just try things until they get the desired result/
<fantasai> AmeliaBR: I would also like to define gradients and transitions to one day use other color spaces
<fantasai> AmeliaBR: e.g. color-interpolation from SVG whch nobody implements :(
<fantasai> AmeliaBR: want to say "mix in LCH"
<fantasai> chris: Had that in spec 10 yrs ago, had to take out
<fantasai> chris: Not that we contro lvia CSS, but antialiasing of forreground shape and bg shape, that also requires interpolation
<fantasai> chris: and that's again different
<fantasai> chris: but it's all linear interpolation and have to specify the color space
<fantasai> leaverou: Drawback to interpolation in LCH?
<fantasai> TabAtkins: Doesn't match
<fantasai> leaverou: but result is same or better?
<fantasai> TabAtkins: proably
<fantasai> markus: So if I'm shifting from red to green, do I go around the circle or through to gray
<fantasai> chris: L axis
<fantasai> chris: black is zeor
<fantasai> chris: 100 is reflective white
<fantasai> chris: on screen whatever native white is
<fantasai> chris: 50% is visually midway between black and white
<fantasai> chris: if you move 10% it is equal -looking steps
<fantasai> chris: then have A and B axis which are cones from your eyes
<fantasai> chris: ... oppostie collor through the L
<AmeliaBR> s/zeor/zero/
<fantasai> chris: ...
<fantasai> chris: LCH is the polar form of that, ou have a hue angle starting from A axis and going round
<AmeliaBR> s/oppostie collor/opposite color/
<fantasai> chris: you have chroma which is like saturation but better
<fantasai> chris: L axis is neutral axis
<fantasai> chris: that's perception
<fantasai> chris: moving by constant amount
<fantasai> AmeliaBR: to ansewr your question, you're converting a color to a vector of 3-4 numbers, and then doing simple interpolation of the numbers
<fantasai> chris: If you itnerpolate LAB you'll get a striaght line
<fantasai> chris: iF you interpolate in LCH you'll also sweep through hue angle, see the rainbow
<fantasai> chris: if you wnat to go through gray then you want LAB
<astearns> q?
<fantasai> AmeliaBR: Can we make a resolution that we all agree color modificaiton functions are a good idea and have them?
<fantasai> q+
<fantasai> chris: I would like us to do that, actually
<fantasai> chris: ppl think we don't care, but we do
<fantasai> TabAtkins: it's just that my previous proposal sucked
<florian> fantasai: my suggestion would be: if we have a clear idea of which proposal we want, we should decide now, but otherwise, we can put both in the spec for now
<florian> fantasai: then it's not just a giant issue, we can work on it, we can iterate, and people can see what we're working on
<florian> chris: I like that idea, but i'd rather do it in css-color-mod-1 rather than css-color-5
<florian> fantasai: I think we should finish color-4 quickly, and then color-5 won't seem that far out
<fantasai> AmeliaBR: If color mod and LCH come togheter can be in the spec
<fantasai> AmeliaBR: we have two proposals right now
<fantasai> AmeliaBR: conrast function seem to all like thate xcept for current bg, so maybe resolve on that?
<fantasai> leaverou: and maybe mixing?
<fantasai> AmeliaBR: So maybe mix with color space option
<fantasai> astearns: LCH is not currently in color 4?
<fantasai> astearns: So could put this into color 4
<AmeliaBR> s/So maybe/And I recognize that blending is nice but confusing, stick with/
<fantasai> fantasai: I think we should put into color 5 and get color 4 into CR
<fantasai> chris: Implementer interest???
<myles_> q+
<astearns> ack fantasai
<fantasai> TabAtkins: We're done with the *spec*, we can put it into CR. Just can't go to REC because waiting for implementations.
<florian> fantasai: we don't want to conflict REC and CR. even if we don't have implementations, if we're done with the spec, it should go to CR
<florian> fantasai: and then this new stuff needs design work, so it should go in different level because we'll file issues, make big changes, etc. So new level or new module
<chris> s/conflict/conflate
<leaverou> q?
<leaverou> q+
<florian> fantasai: I'd prefer color level 5, because it really is the same scope as colors in general
<astearns> ack leaverou
<fantasai> leaverou: One issue with putting i neparate module, if we go with proposal B, it modifies the gramar of the <color> functions
<fantasai> AmeliaBR: That's a good argument for color level 5
<fantasai> astearns: Chris, would you objet to css-color-5?
<fantasai> chris: No, and volunteer to edit
<fantasai> TabAtkins: I don't want to, but maybe Una?
<fantasai> una: sure
<argyle> rad!
<fantasai> astearns: So put some subset of these proposals into css-color-5 with Chris and future Una as editors
<AmeliaBR> s/i neparate/in a separate/
<fantasai> RESOLVED: Put all the proposals into css-color-5, ChrisL and future Una as editors
<fantasai> myles_: Please please please no underscores
<fantasai> chris: Some languages are positional, others need to name them...
<fantasai> TabAtkins: We have lucky thing that function name gives single-letter name of channels
<fantasai> TabAtkins: can use that
<fantasai> leaverou: but what about alpha?
<fantasai> TabAtkins: a
<fantasai> TabAtkins: but LAB?
<fantasai> TabAtkins: other a!
<fantasai> ...
<heycam> rbga(x, y, z, w) => rgb(calc(x + 20), 100, calc(z - 20))
<heycam> to name the arguments you want to use
<fantasai> astearns: let's resolve to put color-contrast in the spec
<AmeliaBR> s/TabAtkins: but LAB?/leaverou: but LAB? It has a, plus alpha.
<fantasai> una: Going to rename color-conrast, color-mod, color-mix
<fantasai> RESOLVED: Rename to put 'color' first, adjust-color -> color-mod()
<fantasai> RESOLVED: Add color-contrast() without currentbg
<leaverou> TabAtkins: why not just .2?
<florian> fantasai: we should make sure we align it with the syntax for crossfade
<florian> fantasai: ... to the extent possible
<fantasai> RESOLVED: Add color-mix(), try to align with cross-fade()
<fantasai> astearns: So two remainign option for color adjust
<fantasai> astearns: could put both in the draft and add an issue that we only need one of htese
<fantasai> astearns: or show why we need both
<fantasai> astearns: or decide now on which to pursue
<fantasai> astearns: anyone have a strong opinion which way to go?
<fantasai> TabAtkins: I'm reasonably leaning towards Una's proposal because I helped work on it
<AmeliaBR> And color-mix suggesting the name of mix() for the generic interpolation of numbers, etc.
<fantasai> fremy: My perspective is, Lea's proposal is very useful but believe storngly we can do that with custom functions
<fantasai> fremy: this is kind of math we cna do with it
<fantasai> leaverou: how does that work?
<fantasai> AmeliaBR: it's a Houdini proposal
<fantasai> astearns: I think that's true of all of these functions
<AmeliaBR> s/cna/can/
<fantasai> fremy: Arbitrary math it's not different from doing math in JS
<fantasai> fremy: but Una's proposal translates to designer vocabulary
<fantasai> fremy: I don't think there's value in creating a new function with special parsing etc. for math
<fantasai> fremy: I would prfer to do a custom function, re-use in your JS
<fantasai> chris: Are you arguing to remove calc()
<fantasai> fremy: what???
<fantasai> astearns: This is not a useful discussion.
<fantasai> leaverou: they are equivalent modifications, just syntax is different
<fantasai> fremy: yes, but if I have to choose between them I prefer the one more scoped to what designers use
<fantasai> una: my proposal is more simplified than Lea's, her's has more power
<fantasai> una: You have to specify each channel even if blank
<fantasai> una: but first proposal is simplified version, do by channel, but using keywords
<fantasai> fantasai: I suggest putting both in the spec, issue at top, request feedback
<fantasai> astearns: Useful to have both proposals in a spec where people can see them
<fantasai> fantasai: and also file issues, improve them, and compare the improved versions as well
<fantasai> astearns: arguments against?
<fantasai> AmeliaBR: It needs to be very cleary set out even if someone is jumping to heading in the document
<fantasai> AmeliaBR: so ppl following along can follow the options
<fantasai> Can also put the .annoying-warning there
<leaverou> basically to use the same example it's color-adjust(blue lightness(120%) chroma(.4)) vs lch(from blue, calc(120% * l) calc(.4 * c) h)
<fantasai> astearns: Also, I expect us to chose only one, but it might be that we end up with both
<fantasai> astearns: if we have good justification have both
<fantasai> una: also might be able to combine them
<fantasai> una: because same calculaitons, less explicitly laid out
<fantasai> ...
<fantasai> TabAtkins: lab vs alpha!
<fantasai> leaverou: write out 'alpha'
<fantasai> myles_: ?
<florian> +1 to putting both in color-5
<fantasai> astearns: My proposal is to put both proposals into css-color-5 with keywords instead of underscores
<fantasai> astearns: and start opening issues to discuss bits we want to modify
<AmeliaBR> s/?/but one is clearly more powerful than the other, it uses calc & you can put anything in there. The other only does multiplications/
<fantasai> RESOLVED: Put both color adjustment proposals into css-color-5, with keywords instead of css-color-5
<florian> fantasai: are there other things we know we should put in color-5?
<fantasai> RESOLVED: Add Lea Verou as editor of css-color-5
<fantasai> Una: we're going to make it happen! As long as you make it happen, implementers :)

@svgeesus
Copy link
Contributor

svgeesus commented Jun 6, 2019

@AmeliaBR said

That said, I'm concerned about reusing calc() if we're also going to add a context-specific token. So my vote would be for rel() or adjust() or something like that. But I still like the idea of having a token for the current variable, to clearly distinguish rel(s + 20%) from rel(s*20%).

I like the generality of calc here. Although the examples so far have been restricted to simple arithmetic operators (+ - * /) on the current channel, it is an advantage to be able to compute from cusstom properties and to use the recently added calc trig functions, for example.

@mirisuzanne
Copy link
Contributor

mirisuzanne commented Jun 6, 2019

I wonder if there is any useful overlap to be found between the _ proposal and other discussions about access to existing values?

They all deal with access to existing, previously-inaccessible values – often with a context-specific token in calc(). Color-space metrics aren't the same as inherited values, but it seems useful to consider them in relation to each other.

@LeaVerou
Copy link
Member Author

LeaVerou commented Jun 6, 2019

the _ proposal

Btw as we discussed in the meeting, if the proposal is adopted, it won't be with _ but with keywords (not yet sure how that's gonna work with color()). I added a quick note to the post above to clarify this, and hopefully I can soon draft it up in Colors 5.

@svgeesus
Copy link
Contributor

svgeesus commented Feb 2, 2020

Btw as we discussed in the meeting, if the proposal is adopted, it won't be with _ but with keywords (not yet sure how that's gonna work with color()).

Lea has now added that proposal to the spec, see https://drafts.csswg.org/css-color-5/#relative-colors

@Crissov
Copy link
Contributor

Crissov commented Feb 3, 2020

This syntax with “local constants” allows to easily switch channels, e. g. rgb(from currentcolor b g r), and it does allow inner colors defined in any valid syntax after from, but authors are limited to the parameters of the outer functional notation they are using, i. e. they cannot access the ones of other notations. Iʼm not sure how useful this would actually be, but I assume authors would expect or even want to be able to do that nevertheless. Wouldnʼt it thus make sense to make them available as well?

This would require unambiguous, multiple-letter monikers for some components of hsl and hwb vs. lch, and rgb vs. hwb vs. lab. The keyword for the opacity channel common to all notations is already spelt alpha instead of a which would clash with lab.


  • red[ness] is a <percentage> that corresponds to the origin color’s red channel after its conversion to sRGB

  • green[ness] is a <percentage> that corresponds to the origin color’s green channel after its conversion to sRGB

  • blue[ness] is a <percentage> that corresponds to the origin color’s blue channel after its conversion to sRGB

  • hue is an <angle> that corresponds to the origin color’s HSL hue after its conversion to sRGB, normalized to a [0°, 360°) range.

  • sat[uration] is a <percentage> that corresponds to the origin color’s HSL normalized chroma (i. e. saturation) after its conversion to sRGB

  • light[ness] is a <percentage> that corresponds to the origin color’s HSL lightness after its conversion to sRGB

  • white[ness] is a <percentage> that corresponds to the origin color’s HWB whiteness after its conversion to sRGB

  • black[ness] is a <percentage> that corresponds to the origin color’s HWB blackness after its conversion to sRGB

  • l-star / bright[ness] is a <percentage> that corresponds to the origin color’s CIE lightness

  • a-star or chroma[ticity]-a is a <number> that corresponds to the origin color’s CIELab greenish-reddish a axis

  • b-star or chroma[ticity]-b is a <number> that corresponds to the origin color’s CIELab bluish-yellowish b axis

  • chroma is a <number> that corresponds to the origin color’s LCH chroma

  • h-star is an <angle> that corresponds to the origin color’s LCH hue, normalized to a [0°, 360°) range.

  • alpha is a <percentage> that corresponds to the origin color’s alpha opacity transparency


This would also allow to make further values available in the future, which do not need to have dedicated notations, e. g. HSI intensity (relative chroma), HSV relative value, HSB absolute brightness; grayness; XYZ tristimulus-x; luminosity (W, J/s), YUV luminance (linear y, nit, cd/m²), Y'UV / Y'CC luma (y-prime), chroma[ticity]-u, v-star, chroma-blue (Cb, Pb), red-cyan (Cr, Pr), chrominance, colorful[ness] (saturation as relative colorfulness, chroma as comparative colorfulness;), blue-luminance (U), luma-v; YIQ orangish-bluish (I), purple-green (Q), CMYK cyan[ness], magenta[ness], yellow[ness] , key; tint, tone, shade; radiance

Btw., I believe it is counter-intuitive that angular hue would be converted to a <number>, so I kept <angle>.

@svgeesus
Copy link
Contributor

svgeesus commented Feb 3, 2020

they cannot access the ones of other notations. Iʼm not sure how useful this would actually be

I can't imaging a use case for computing, say, 30% of the CIE L, 20% of the sRGB green channel, and 50% of the HSL hue.

Making the syntax more cumbersome to allow for a possibility with no use case does not seem like a win.

@svgeesus
Copy link
Contributor

svgeesus commented Feb 3, 2020

@una wrote

Another idea for implementation: https://gist.github.com/una/edcfa0d3600e0b89b2ebf266bf549721

@una has now added that proposal (as modified by CSS WG discussions in Toronto) to the spec too, and the co-editors have been working on illustrative examples.

color-mix()
color-contrast()
color-adjust()

@Crissov
Copy link
Contributor

Crissov commented Feb 4, 2020

Itʼs probably impossible to imagine realistic use cases for every color component combination, but finding a single one would already mean, that the identifiers needed to be unique across functional notations, in my humble opinion.

Would it be conceivable, for instance, that someone wanted to use CMYK key as HWB black or its cyan, magenta and yellow components as RGB channels?

hwb(from device-cmyk(10% 20% 30% 40%) 180deg 50% key /*= 40%*/)
rgb(from device-cmyk(10% 20% 30% 40%) magenta yellow cyan / key)

Would someone want to transplant an sRGB HSL hue or lightness into CIELab LCH?

lch(from hsl(180deg 50% 80%) lightness /* = 80% = 0.8 */ chroma hue /* = 180deg */)
hsl(from lch(0.5 0.8 180deg) h-star sat l-star /* = 0.5 = 50% */)

You could effectively write custom conversion operations this way.

@AmeliaBR
Copy link
Contributor

AmeliaBR commented Feb 4, 2020

realistic use cases for every color component combination

When and if such use cases arise, the author could use nested functions. The result of one adjustment could be the "from" value for another adjustment.

@Crissov
Copy link
Contributor

Crissov commented Feb 20, 2020

@AmeliaBR I first thought this made absolute sense, but I cannot come up with some actual nested syntax that would result in k from device-cmyk() being used for b in hwb(), for instance.

hwb(from device-cmyk(10% 20% 30% 40%) 180deg 50% b/*?*/)

@LeaVerou
Copy link
Member Author

Btw, I posted some of the findings from HTTPArchive that relate to this in #5782.

@w3c w3c deleted a comment May 16, 2021
@svgeesus
Copy link
Contributor

Closed by WG resolution to drop color-adjust() and retain RCS

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