WICG / color-api

A proposal and draft spec for a Color object for the Web Platform, loosely influenced by the Color.js work. Heavily WIP, if you landed here randomly, please move along.
https://wicg.github.io/color-api/
Other
130 stars 3 forks source link

[Color.parse()] What is the space of accepted CSS color strings? #39

Open LeaVerou opened 3 months ago

LeaVerou commented 3 months ago

What happens if authors try to parse things like

  1. "oklch(50% 10% var(--hue))
  2. "oklch(50% 10% calc(0 + 20))
  3. "color-mix(in oklab, currentColor, red)"

The Color API is not Typed OM, so the internal representation of the color needs to be concrete numbers. However, it can still accept color strings that are not just a color space function with specific coords, and resolve them to numbers.

Each of these examples brings up different questions around this:

  1. Should the API provide some way to specify what the context is, so that variables and things like currentColor or system colors are resolved? (an object literal, or even a DOM element)
  2. Should the API follow calculations in calc() if they can be resolved?
  3. Should color functions like color-mix() be accepted if they can be resolved?

And when a color is valid CSS, but not something the Color API can handle, what should happen? We throw an error or do something else?

tabatkins commented 3 months ago

Ideally it accepts the full range of CSS syntax, so you can feed it a CSS value and get a color out.

This means I think it should accept calc() and friends, at least.

But if given something that relies on information it doesn't have access to (non-absolute dimensions, currentcolor, variables), it should either fail to parse (probably the most reasonable) or resolve based on initial values, like MQ does (but this doesn't guarantee predictable evaluation, since, for example, the initial value of color depends on the page's color scheme, the initial value of 1em depends on the user's default font size, etc).

And when a color is valid CSS, but not something the Color API can handle, what should happen? We throw an error or do something else?

Throw, just like a straight-up invalid value. It's essentially the same error path. We can throw a different error message, perhaps - either they're both SyntaxErrors, but with different messages, or invalid syntax is a syntax error, and valid-but-unhandleable syntax is, uh, a DataError? https://webidl.spec.whatwg.org/#dfn-error-names-table

svgeesus commented 3 months ago

But if given something that relies on information it doesn't have access to (non-absolute dimensions, currentcolor, variables), it should either fail to parse (probably the most reasonable) or resolve based on initial values, like MQ does (but this doesn't guarantee predictable evaluation, since, for example, the initial value of color depends on the page's color scheme, the initial value of 1em depends on the user's default font size, etc).

I agree that parse failure is more useful here than initial values which as you say are context dependent.

By the above, do you mean "variables are not available" or "if that variable is not available"?

LeaVerou commented 3 months ago

I agree that throwing is better than resolving with initial values, which is rarely what you want.

I think it would be illuminating to concretely enumerate the cases in which we don’t have enough information to resolve the color. So far we have mentioned:

  1. CSS variables
  2. currentColor
  3. system colors
  4. non-absolute dimensions (mainly via division between them)

Is this an exhaustive list or are there others too?

I would love to explore ways to have our cake and eat it too, i.e. provide the necessary context (possibly not in v1). Ideally in a way that does not exclude JS runtimes from implementing this API, which is going to be tricky (if that was not a consideration, we could simply provide a DOM element reference and poof, all problems are gone). This would make it so much more useful for e.g. use cases like code editors, code playgrounds etc. (which currently fail miserably at showing a color preview in these cases). In some ways it seems similar to the URL constructor, which accepts either an absolute URL, or a relative URL and a base. But to figure out the best API shape for that, we need an exhaustive list of these cases.