-
Notifications
You must be signed in to change notification settings - Fork 719
[css-color-4] Color modifications proposal: extending color functions #3187
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
Comments
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 For example, with the current addition facilities for animation one can already bump up the green channel by adding |
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 Instead, I think they should all be the same mandatory-ness as usual, and we use your |
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 One benefit of the optional argument syntax that is now lost is that it's also a color space conversion syntax. |
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 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. |
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.
With RGB, the single provided percentage value might even apply to the first, red channel. |
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. |
🆗 |
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 What about keywords and +/-?
Or:
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
Testing longer keywords again: I kind of like using
|
While keywords usually increase readability, in this case since there are no commas to group the different arguments. Therefore, keywords like Using I love the idea of using |
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 I find the use of the component initials as the placeholder for the starting value more intuitive & easier to read than I like the idea of using a 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 |
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. |
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
That said, I'm concerned about reusing |
I agree that named components are far more intuitive, I'm just not sure what happens in the case of |
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 |
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 But that makes me thinking that in addition to a relative adjustment function, there should maybe be a |
@AmeliaBR All existing color functions are defined as operating in sRGB, e.g. look here for rgb(). |
@LeaVerou from a later paragraph in that section:
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 |
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.
It is impossible to not implement it :) a device can't display colors outside it's gamut, by definition. |
I was under the impression that |
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 So in addition to:
It seems it would be nice to have an option for:
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
This would modify the If there was a function to pick color based on contrast, perhaps something like In terms of blending, |
I figured I'd make some edits to the original proposal that reflect the discussion so far, and my take on the issues raised. ProposalThis is loosely inspired from the current practice of defining major theme colors as color components in a variable (e.g. I’m proposing to extend all color functions to allow for a Edit: As of the June 5 F2F discussion, we are not going to use Before any modification, the color would be converted to the target color space of the function used. This means that modifications using 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 Examples
Benefits of this syntax
Drawbacks
|
Another idea for implementation: https://gist.github.com/una/edcfa0d3600e0b89b2ebf266bf549721 |
The CSS Working Group just discussed
The full IRC log of that discussion |
Uh oh!
There was an error while loading. Please reload this page.
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
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
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_
orsame
keyword can be used to mean "no change". For example, if a function’s grammar is{3}
, it will become? ( | _){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 withlab()
orlch()
. 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()
: Multiplies the color component by
. E.g.lab(red rel(60%) rel(100%) rel(100%))
would convertred
to Lab, and then multiply its L by 60%.up
/down
: Relative addition/subtraction. The previous example would belab(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.calc()
. E.g. the previous example would belab(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
Drawbacks
cross-fade()
, since we need to address this for interpolation too?hsl()
color, with the gamut limitations that this comes with.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.The text was updated successfully, but these errors were encountered: