- From: Lea Verou via GitHub <sysbot+gh@w3.org>
- Date: Wed, 06 Mar 2024 03:34:29 +0000
- To: public-css-archive@w3.org
LeaVerou has just created a new issue for https://github.com/w3c/csswg-drafts: == [css-color-5] `color-scale()` for interpolating across multiple colors == During the discussion in #9992 it occurred to me that one of the things that could really help simplify the color-related design systems use cases would be a way to define a gradient line and pick a color on it. ## Why? - As a primary use case, authors often need to define scales of colors with interim colors inserted to adjust the interpolation, and `color-mix()` is not very friendly to that. Super common example: the good-bad scale of red, orange, yellow, green. - Design systems could then define color scales and pass them around in variables, which would make functions a much more appealing solution for actually selecting points on those scales. - It makes interpolation with arbitrary manual interim points much easier, without requiring special overfit syntax in variable groups to cater to this. - The scale specification should be compatible with gradient color stops so that authors can debug them by simply throwing them into a `linear-gradient()`. ## Syntax ### Option 1: Single function for both *defining* the scale, and _selecting_ a color ``` <color-scale()> = color-scale ( <percentage> / <color-interpolation-method>?, <abstract-color-stop-list> ) <abstract-color-stop-list> = <abstract-color-stop> , [ <abstract-color-hint>? , <abstract-color-stop> ]# <abstract-color-stop> = <color> <percentage>? ``` Example usage: ```css --tints-green: white, var(--color-green), black; --color-green-900: color-scale(90% / var(--tint-green)); ``` This is basically modeled after `linear-gradient()` with the non relevant parts removed (lengths, `to <whatever>`, angles). It could also allow `<1d-image>` / `stripes()` to facilitate discrete scales. The reason the percentage is separated from the rest with a `/` is to facilitate storing the actual scale part into variables and passing them around without having to worry about whether you need to specify a comma or not (depending on whether the scale has a `<color-interpolation-method>`). Pros: - By passing a list of arguments around, these can produce *both* a color scale *and* various types of gradients (without gradients having to be extended in any way) - Color stop list could even be extended by adding more stops on either side Cons: - Scale variables don't make sense by themselves, as they're just a comma-separated list of colors. ### Option 2: Separate scale definition and color selection This syntax decouples the scale from the color selection. It seems more conceptually sound, but also too many parens. ``` <color-scale> = color-scale ( <color-interpolation-method>?, <abstract-color-stop-list> ) <abstract-color-stop-list> = <abstract-color-stop> , [ <abstract-color-hint>? , <abstract-color-stop> ]# <abstract-color-stop> = <color> <percentage>? <color-pick()> = color-pick(<percentage> of <color-scale>); ``` Example: ```css --tints-green: color-scale(white, var(--color-green), black); --color-green-900: color-pick(90% of var(--tints-green)); ``` the parens could be reduced if it would be possible to define tokens like: ``` <color-scale-color> = <percentage> of <color-scale> ``` Example: ```css --tints-green: color-scale(white, var(--color-green), black); --color-green-900: 90% of var(--tints-green); ``` but I suspect @tabatkins will have a good reason to rule that out 😁 We could also make it a variant of `color-mix()`: ``` <color-mix> := color-mix(<percentage> of <color-scale>) ``` Example: ```css --tints-green: color-scale(white, var(--color-green), black); --color-green-900: color-mix(90% of var(--tints-green)); ``` Though since conceptually we're not mixing anything, I don't think this is worth it. ## More Examples ### Transparent variations of a base color Option 1: ```css --color-neutral-a: var(--color-neutral), transparent; --color-neutral-a-90: color-scale(90% / var(--color-neutral-a)); ``` Option 2: ```css --color-neutral-a: color-scale(var(--color-neutral), transparent); --color-neutral-a-90: 90% of var(--color-neutral-a)); ``` ### Success/failure scales This is super common to communicate varying levels of success/failure. There are two main forms: red - orange - yellow - green - dark green, or red - white - green. E.g. see screenshot from Coda’s conditional formatting: <img width="329" alt="image" src="https://github.com/w3c/csswg-drafts/assets/175836/9215ca1c-89e2-4d9a-aa2e-04de367afc91"> Especially the red - orange - yellow - green scales almost always require manual correction, and cannot be done with a single 2 color interpolation (yes not even in polar spaces). With `color-scale()` they can be as simple as: ```css :root { --color-scale-bad-good: in oklch, var(--red), var(--orange), var(--yellow) 50%, var(--green) 90%, var(--dark-green); } .badge { background: color-scale(var(--percent-good) of var(--color-scale-bad-good)); .great { --percent-good: 100% } .good { --percent-good: 80% } .ok { --percent-good: 60% } .fair { --percent-good: 40% } .poor { --percent-good: 20% } .terrible { --percent-good: 0% } } ``` Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/10034 using your GitHub account -- Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config
Received on Wednesday, 6 March 2024 03:34:31 UTC