Skip to content

[css-color-5] Fallback strategy for nonexistent color spaces? #6129

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

Open
LeaVerou opened this issue Mar 23, 2021 · 10 comments
Open

[css-color-5] Fallback strategy for nonexistent color spaces? #6129

LeaVerou opened this issue Mar 23, 2021 · 10 comments
Labels
css-color-5 Color modification

Comments

@LeaVerou
Copy link
Member

LeaVerou commented Mar 23, 2021

This comes from #5931, which is a closed issue. Here is the discussion so far:

#5931 (comment) by @svgeesus:

Do we also need a way for authors to provide fallbacks for nonexistent color spaces, which was another function of the fallback parameter?

Nonexistent colorspaces result in invalid color which produces opaque black.

#5931 (comment) by @LeaVerou:

Do we also need a way for authors to provide fallbacks for nonexistent color spaces, which was another function of the fallback parameter?

Nonexistent colorspaces result in invalid color which produces opaque black.

How would authors be able to handle failure here? Especially since custom color spaces depend on separate HTTP requests, which could always fail for whatever reason. We don't want websites to suddenly turn all black because an HTTP request failed, do we? That would be terrible, both for accessibility and usability.

Some thoughts:

  • What if instead of opaque black, the property becomes invalid at computed value time, which would set it to unset. That is a far more reasonable fallback for most cases.
  • I wonder if instead of having a color fallback, we should really have color space fallbacks. What do I mean by that? A @color-profile descriptor that basically says "if my ICC profile doesn't load, treat my coordinates as this color space". E.g. if we link to a profile for OKLab and it doesn't load, treat coords as Lab. Or if we link to an RGB profile, we can say, as a fallback, treat params as sRGB or P3 or whatever built-in RGB color space is closest to the one we linked to.

#5931 (comment) by @tabatkins:

I'm not strongly opposed to doing more IACVT, but I'd like to avoid adding it to more things if we can; it's an awkward compromise that still doesn't give any guarantee that the result is readable.

I do quite like the "color space fallback" idea, designating which of the predefined colorspaces treats its first three arguments "close enough" to your desired colorspace to work as a last-ditch substitution. That seems to solve the problem quite well. Should we choose a default for this, or require it to be explicitly specified on each @color-profile rule?

#5931 (comment) by @faceless2:

I also really like the "color space fallback" solution. Assuming the author hasn't just messed up, the way this is going to come into play is if the profile is unavailable. Lea's suggestion would almost certainly be the least visually jarring result.

Obviously if we have @color-profile foo { src: url(missing.icc) } we don't really know enough about the missing profile to determine which space to choose as a fallback. A presumption based on the number of components is what I'd suggest - one component is grayscale, three is sRGB, four uses device-cmyk.

This will fail for lab profiles, and for "exotics" with two or more than four components - which can just fall back to black as they do now. And three color spaces that are not RGB are super rare in the real world. Given we're falling back to black now, falling back to an equally incorrect color isn't a step backwards. While testing I frequently turned whole pages black, as my missing profile meant both text and background were black. Frankly anything is an improvement over that.

#5931 (comment) by @LeaVerou:

While testing I frequently turned whole pages black, as my missing profile meant both text and background were black. Frankly anything is an improvement over that.

Yup, that is exactly what I was trying to avoid, so I think failing to opaque black is unacceptable in any case.

Probably the best possible fallback will come from the fallback color space. Note that this could also provide a good fallback while the profile is loading, preventing huge color shifts, which would otherwise deter many authors from using ICC profiles. People could even use it as progressive enhancement. I have also heard there were concerns from the Blink team about having colors that depend on an HTTP request, hopefully this should help alleviate them.

However, there is not always a built-in color space that is reasonable, so I don't think we can make this descriptor mandatory. While most ICC profiles are RGB and CMYK, they are not the only ones. This is where IACVT comes in, which, as a last resort, produces far more accessible results than just opaque black everywhere. If we don't want to use IACVT, another option might be to use the property's initial value if that is a color, otherwise transparent. This prevents the "black text on black background" problem, and doesn't make the entire declaration invalid like IACVT would.

#5931 (comment) by @carlosame:

Although I'm reluctant to post in closed issues, I want to add that "opaque black" is probably not the most adequate choice because it is not printer-friendly. As was mentioned, it is possible that large chunks (or entire pages) of a document become black, and for printing use cases a likely outcome is the toner cartridge being wasted. white or transparent seem more sensible choices, toner-wise.

@carlosame
Copy link

carlosame commented Mar 23, 2021

custom color spaces depend on separate HTTP requests, which could always fail for whatever reason

Even if the http request succeeds, in some cases the custom profile may fail. In a comment to #5931 I summarized four hypothetical profile failure cases, the first one being that the profile type may not be supported by the device.

One example of a profile format that may or may not work is iccMAX, moreover in the future a browser (or a printing software) may support some non-ICC profile on certain platform and then some authors may decide to use it, despite other UAs (or other platforms) not allowing that.

My point is that this issue is wider than just "the http request failed" or "the request took too long to complete".

@fantasai fantasai added the css-color-4 Current Work label Mar 23, 2021
@svgeesus
Copy link
Contributor

svgeesus commented Oct 9, 2021

One option might be to use the length of the components descriptor; if 1 assume rgb(grey grey grey), if 3 assume rgb(red green blue) and if 4 assume `device--cmyk(cyan magenta yellow black).

The red green and blue values would of course be scaled from [0,1] to [0%,100%].

@LeaVerou
Copy link
Member Author

LeaVerou commented Oct 9, 2021

We absolutely should not assume that any linked ICC profile is RGB-based or CMYK-based by number of coordinates, that's super flimsy, and I don't see how it's better than having explicit color space fallbacks.

@carlosame
Copy link

Part of the problem is that I do not see a specific use for the components descriptor, not only for this use case but in general. One could try to infer the color model from the names of the components, like

components: red, green, blue

which is clearly RGB but the component names aren't normalized so someone could have

components: rojo, verde, azul

and you are screwed.

From my point of view, it would be more useful to have a color-model descriptor which could take any values from Table 19 in the ICCv4 specification (I have v4.3 aka ICC.1:2010), plus HSL and HWB (I already suggested using this in a color-related Houdini issue):

iccv4-table19

Without knowing the color model, one cannot serve the most basic use case for a color space: a color picker, nor can provide an approximate fallback color.

@LeaVerou
Copy link
Member Author

LeaVerou commented Oct 9, 2021

Part of the problem is that I do not see a specific use for the components descriptor, not only for this use case but in general.

The point of the components descriptor is that without names, the components cannot be tweaked via relative color syntax etc. It was never designed for inferring color model.

@Crissov
Copy link
Contributor

Crissov commented Oct 10, 2021

You could safely fall back by number of components if color space identifiers were used inside existing function notations, as I suggested in #6642. For color(), it seems too fragile.

@svgeesus
Copy link
Contributor

Within a relative color syntax color() function using , the number and name of the allowed channel keywords are:

@svgeesus
Copy link
Contributor

From my point of view, it would be more useful to have a color-model descriptor which could take any values from Table 19 in the ICCv4 specification

I did look at that, but it is a poor fit for CSS Color 4:

  • 14 of the descriptors just give the number of channels, without saying what they are
  • Luv, YCbCr Yxy and Gray are not used

So basically it comes down to saying that

  • the predefined RGB models are RGB
  • HSL is HSL
  • HWB is not defined
  • Lab is Lab
  • XYZ is XYZ
  • and, usefully, that CMY is CMY and CMYK is CMYK

So it seems to add some complexity but only marginal value.

@carlosame
Copy link

  • HSL is HSL
  • HWB is not defined

In fact the table has HLS intead of HSL, that's why I suggested adding HSL and HWB.

So it seems to add some complexity but only marginal value.

It adds reliability, which should not be dismissed: if you know that your color space uses RGB (as opposed to just assuming it), you are certain about what the approximate rules are if you want to derive a fallback. And you could add a colorimetric definition to the color model, to have a more accurate derivation of the fallback. That would be more complex, admittedly.

That said, there is the question that perhaps most use cases of custom profiles would want either a full success or an easy-to-detect failure (unless they configure an explicit fallback-related descriptor like the one mentioned above or what @LeaVerou suggested earlier).

@svgeesus svgeesus added css-color-5 Color modification and removed css-color-4 Current Work labels Nov 19, 2021
@svgeesus svgeesus changed the title [css-color-4] Fallback strategy for nonexistent color spaces? [css-color-5] Fallback strategy for nonexistent color spaces? Nov 22, 2021
@mclegrand
Copy link
Member

I'm starting to look at the current CSS standard options to define specific colors for SVG2 (in Inkscape), and the complete disappearance of fallback in color(), or of any fallback mechanism, is puzzling me a lot:

Our use case could be something like « I'm making a SVG poster/art for print which I'd also like people to be able to see in rec2020 on their computers, but of course it should display fine if your screen only supports sRGB », and looking at what to put in the fill="..." attribute (or equivalently style="fill:...") I see nothing like what I currently have in SVG11 : I can now only specify <color> for one context.

Given that --my-profile cannot be guaranteed to exist for people viewing the file if I don't embed the whole icc in base64 in the svg, using it directly (without fallback) seems impossible, so all that's left possible seem to be defining all colors in the file in xyz or lab and handling any color profile operations with non-standard attributes (something like fill="lab(...)" inkscape:orig-fill="icc-color(...) #00ff00"). This would be a huge issue for interoperability and conversions, as we would, ideally, like to be able to export "standard" svg to .sla (Scribus) or to pdf with the expected color profiles without relying on nonstandard attributes (and while using the color profile, to not lose ink information).

The assumption (in #5931) that I could use media queries implicitly suggest that I should give all my colors unique identifiers and a CSS chunk defining them all in all contexts (also I don't recall a media query for "this icc file exists on the system") instead of being able to name them in the attributes which, I guess, could potentially work (?), but would be a pain for file size as well as for parsers exporting to other formats.

I understand that thinking about color-mix and color-adjust is harder with the existence of fallback colors but I don't understand what they were replaced with, conceptually… the simplest for me would be to suggest that non-loadable icc make colors go IACVT, and either that <color> is replaced with <color-list> (or <color> = <absolute-color-base> | currentcolor | <system-color> | <device-cmyk()> , <color>?) and that the first computable displayable value in the list is the actual color; or that I could deal with a non very satisfying <rect style="fill:#0f0;fill:color(--my-profile, ...)"> where the last valid value might prevail, but can't work with the fill xml attribute...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
css-color-5 Color modification
Projects
None yet
Development

No branches or pull requests

6 participants