Closed tabatkins closed 8 years ago
As long as we don't allow the ident and the args to be freely intermixed, like color(127 foo 255 64). Because for named color profiles, the arglist includes identifiers not just numbers.
Right, as long as the color profile name comes first, we're good. I'm in favor of Tab's proposed change (though I don't care strongly).
SGTM
I don't have a strong opinion, but I'd like to avoid a situation where we have this:
color(adobe-rgb 0.5 0.5 0.5, 0.5)
Okay, you wanna be radical, let's be radical:
<alpha-value>
nonsense, and just use <percentage>
for the alpha. (Allowing multiple ways to write each arg is, I think, one of the mistakes of earlier color functions.)srgb
predefined colorspace.srgb
.We can then treat rgb()/rgba() as legacy syntaxes for specifying RGB colors (and hsl()/hsla() are already legacy, since hwb() is more intuitive for srgb stuff, and lch() is generally better overall).
(I'm not being facetious, I think this whole list is a great idea.)
With the caveat expressed in https://github.com/w3c/csswg-drafts/issues/275#issuecomment-231311567 (if we make the color space optional, I'd prefer to keep the coma after it), I'm OK with Tab's proposal.
This is rad!
color(foo .1 .2 .3 .5)
is a color with 3 params that is 50% opaque or a fully opaque color with 4 params.color()
is bound to create a ton of confusion.I'm also not sure about dropping the comma between the color space and its params either. When things in CSS are space-separated, people expect to be able to use any order, unless there is an obvious ambiguity (e.g. all numbers). I think when there is a specified order, it's more clear to have a comma.
I... I don't understand what you people have against percentages. It's "industry practice" to use 0-1 floats because those languages (mostly C++) don't have any standard way to do typed-numbers and so just expose them as floats. CSS does have easy ways to do typed numbers, which are trivial to use and aid in readability.
Like, Lea says in her comment that color(foo .1 .2 .3 .5)
is hard to read, because it's unclear whether the fourth number is a fourth arg to the colorspace or the alpha (I agree). But if you just write color(foo .1 .2 .3 50%)
, that problem completely disappears - it's now 100% obvious that the last one is an alpha, even at a casual glance. I argue that this is easier to read than color(foo .1 .2 .3, .5)
, and they're exactly the same number of characters, so the "save bytes" argument doesn't apply.
When things in CSS are space-separated, people expect to be able to use any order, unless there is an obvious ambiguity (e.g. all numbers). I think when there is a specified order, it's more clear to have a comma.
I don't think it's unusual to have "names" come before "arguments". Everything else about this function is precisely ordered already, and I somewhat agree with dino's argument that we shouldn't make it difficult to remember where the commas need to be.
One of the big criticisms of rgba() is that the 'a' part is in a different number format (0-1, vs. 0-255). If 'color()' with rgb and 'a' parts is similarly inconsistent (0%-100%, vs. 0-1), then it isn't an improvement on that front.
Commas are reasonable ways to separate groups of values in CSS. So are slashes, when commas won't do. I think having a distinctive separator on either side of the color components would be a good thing, and would improve readability. It would also mean we could allow the author to choose between 0-1 and 0%-100% for each of the r,g,b, and a components. That would be nice. Thus, the author could use all 0-1 for consistency with legacy alpha and between numbers, or use all percentages if they want.
I'm tempted to ask what "you other people" have against decimal number, but anyway. Percentages are fine where they are appropriate and natural. Percentages in rgb() were used purely because number without percent were already taken, and referred to a 0 to 255 scale, thus making the values of 0 and 1 ambiguous unless % was used as a flag.
Lea says in her comment that color(foo .1 .2 .3 .5) is hard to read, because it's unclear whether the fourth number is a fourth arg to the colorspace or the alpha (I agree). But if you just write color(foo .1 .2 .3 50%), that problem completely disappears - it's now 100% obvious
Right, until you write color(foo 10% .20% 30% 50%) and then it is hard to read again. A comma (or slash, as brad suggests) would help there.
Based on the July 13, 2016 CSSWG conf call we have resolved to:
<number>
and <percentage>
Remaining decision is about commas in color related functions with the following options:
There's also the remaining question, assuming we don't require commas in color(), of whether to use a slash as ChrisL suggests.
I'm currently leaning towards no commas in color(), since the syntax allows keywords, has optional arguments, etc. which are more CSSy than traditional functions. But I also lean towards requiring the slash for readability, since as ChrisL points out, it's hard to visually parse a color consisting of all percentages. And imho percentages are the most natural way to represent a range between 0 and 1, so they should be comfortable to use for all of the color coordinates.
[While we're at this, btw, we should also review all our other functions for consistency. The comma-less syntax we're discussing here is consistent with the attr() function in V&U, but Grid's repeat(), for example, probably doesn't need its comma either.]
I was thinking of something along these lines, to avoid multiple nesting of color()
functions in the fallback:
[<color-channel-args>[/<alpha>||<ident>]?]# [, <non-color()-fallback>]?
Or variations on this theme:
[[<ident>/]? <color-channel-args>[/<alpha>]?]# [, <non-color()-fallback>]#
Thus, commas only used for fallback list. By the way, the spec doesn't seem to say when fallback is used, and I wasn't in that conversation of the f2f. Is it when a color profile can't be used because it doesn't fit within the gamut of the device?
it's hard to visually parse a color consisting of all percentages.
Nothing but the alpha can be a percentage. The rest are numbers.
And imho percentages are the most natural way to represent a range between 0 and 1, so they should be comfortable to use for all of the color coordinates.
The color coordinates aren't necessarily 0-1. That's common, but there's nothing requiring that. They're not appropriate to be percentages.
I was thinking of something along these lines,
There's no need for any of those slashes; they serve no purpose for disambiguation. And there's no need for a comma separating the fallback from the rest, for the same reason. color() is also allowed in fallback, intentionally - you can fallback to a different colorspace.
Is it when a color profile can't be used because it doesn't fit within the gamut of the device?
No, it's for when a color profile is invalid or unknown. Color profiles already define how to scale themselves down to fit smaller gamuts.
Y’know, for subjective arguments like “easier to read” there are actually rather objective empirical tests possible. Standardizing bodies don’t have a great history of conducting user studies, though: it’s usually the best (or loudest) articulated argument in a committee of experts that decides such issues. (That’s not saying that corpus analyzes of existing content didn’t help to back one’s argument already.)
I just posted this as a question on Twitter. The overwhelming consensus is that people want commas. https://twitter.com/jensimmons/status/753664695563943936
"I'd be ok with optional commas, but mandatory absence of commas seems like it would constantly trip me up." — Zing Web Creak
"I l like commas, it's consistent with other functions" — Ire Aderinokun
"It's one thing to accept a version without commas, but commas are standard, so shouldn't cause an error." — Estelle Weyl
"I prefer commas, both for consistency and because they’re an extra visual cue that can help avoid errors." — Eric Meyer
[Replying to Eric Meyer] "Agreed. There’s less ambiguity there." — Aaron Gustafson
[Replying in the same thread] "With you all: commas - if it looks like bunch of parameters being passed, separate them. Also, lessens the cognitive load when everything has the same convention [rgb(), translate3d(), etc]" — Chris Casino
[And Eric again, replying] "Yep. I already struggle with the syntax of circle() and ellipse(), which don’t allow commas. " — Eric Meyer
One person did say: "no commas, just like { padding: 1em 0 2em; }" — Chris Johnson but he was the only one who thought no commas is more consistent with the rest of CSS. Most others argued that having commas is more consistent with the rest of CSS.
You can find more replies by clicking the above link. Many were simple "yuk" statements, in response to the code snippet I included that showed no commas.
I don't think the way that your informal twitter survey was phrased is accurately portraying the choice we're trying to make. You listed old functions with commas and a new function without, where the predominant proposals on the table are to have optional commas in the old functions and possibly optional commas in the new function. There's also no comparison to other css functions that already don't allow commas between certain arguments. I suspect this is biasing the results.
Maybe try again with something like: repeat(2, [a] 1fr [b]); circle(at 50% 50%); rgba(255, 255, 255, 0.6); hsl(240, 100%, 50%); newcolorfunction(.1, .2, .3, 50%);
vs:
repeat(2, [a] 1fr [b]); circle(at 50% 50%); rgba(255 255 255 0.6); hsl(240 100% 50%); newcolorfunction(.1 .2 .3 50%);
There's no need for any of those slashes; they serve no purpose for disambiguation. And there's no need for a comma separating the fallback from the rest, for the same reason. color() is also allowed in fallback, intentionally - you can fallback to a different colorspace.
Having multiple nestlings of color() in order to get multiple fallbacks is exactly what I don't like about that. It's ugly and unreadable. It would be better, and more consistent with other CSS, if commas were used for separating the multiple fallbacks WITHOUT having to repeat the color(
on one side and )
on the other. And once you do that, then comma is no longer available as a visual separator of the subgoubings. Thus, a slash instead.
Imagine if for font-family
fallbacks, we had to write something like this:
font-family: font-family(helvetica font-family(arial font-family(sanserif)));
That's basically in line with what you want for color: color()
fallbacks.
I think this is more readable:
color: color(bradsMonitorRGB/20 30 40, AdobeRGB/21 29 41, AdobeRGB1998/21 32 40, sRGB/22 32 45)
(Numbers are just made up for this example)
@bradkemper If there are commas, what's the point of the slash?
@leaverou what I proposed is that the commas are separating compound values in a list of fallbacks (color() values, not complete functional notations of color()
). So if they are used for that, then they shouldn't be used within each compound value in that list. That would be confusing, and harder to read. So a slash would be a separator of the sub-value groups, to group and separate the color channels from the alpha and/or profile identifier.
Maybe a separator would not be necessary for the profile identifier, but it would help distinguish the alpha from the other component values (without making the alpha seem like a separate item in the list of fallbacks).
Once you do have a slash, you can put alpha and profile identifier on one side of the slash, and color channels on the other.
Note how with image-set()
, for example, the commas are just for separating items in a list, where each item is itself a compound value. The list of color stops inside linear-gradient()
is similar. If an additional separator was needed within each item, I wouldn't expect it to be another comma.
That sounds like yet another reason to separate alpha with a comma. There is no reason to keep re-specifying the same alpha value for each fallback.
Oh, I see. Just have it there once? I hadn't considered that. It'd be a little odd, having it on one end or the other of a list of fallbacks, but but I guess that'd work. I'm used to seeing it right after the color channels (in rgba(), etc.), so it seems more natural to me to travel with each set of color channels. Hmm.
I sometimes do this sort of thing, for abs pos stuff like menus or tool tips::
background: rgba(255,255,255,0.95)
That gives me a white background with just enough translucency to tell that there is stuff behind it, without interfering too much with the readability of the text in front of it.
Might I not want to set a lower alpha opacity to the color for a color space that tended to blow out the lighter colors, so that I could still see some lighter gray patterns through it? If so, then I'd want the alpha associated with the color space.
So far my favorite proposal here is color( [ <colorspace>? <number>+ [ / <alpha> ]? ]# )
. I think Brad's suggestion of using commas for the fallbacks--and therefore not internally to a color--makes sense. I agree that nesting color functions is awkward. There's no reason not to just use commas here and indicate rgb or hsl with those keywords--it's easier to type, works better when chained, and is consistent across all arguments: color(adobeRGB 0.2 0.6. 0.4 / 100%, rgb 0.2 0.67 0.5 / 100%)
Since we'd also want to allow keywords and #rgb notation, the full proposal then would be
color( [ <colorspace>? <number>+ [ / <alpha> ]? ]# [ , <color> ]? )
I could go either way on the slash if indeed only <alpha>
can take a percentage, but I'm not convinced that's a good restriction to introduce for all time.
This proposal makes sense to me, but since we also want to support named colors from an icc profile, it should probably be amended to this:
color( [ <colorspace>? [ <number>+ | <string> ] [ / <alpha> ]? ]# )
or
color( [ <colorspace>? [ <number>+ | <string> ] [ / <alpha> ]? ]# [ , <color> ]? )
I'm very skeptical about the slash. It's completely different than what any other color function is doing. Also we've seen in other microsyntaxes that if something is separated by a slash, authors don't use it very much (e.g. border-radius
, background
shorthand). The only exception is the font
shorthand, because there it was common practice before CSS to refer to [font-size]/[line-height] so it was externally consistent.
@fantasai @frivoal I'd support that variation.
@leaverou I don't think having a slash would equate to authors not wanting to use it. With border-radius
, it just isn't needed that much because the vast majority of border radii are symmetrical with regard to vertical and horizontal. Also, it is a little confusing and harder to remember that when specifying the two axes on a single corner (with border-top-left-radius
for instance), no slash is required between the two values, but when using the border-radius shorthand, you do need a slash between the two axis values.
With the background shorthand, there was a long time when background shorthands didn't support inclusion of background-size, and authors got used to writing it separately. Even today, it is often a separate thought to change the default size of the background size (at least for me, when I use it). It is also often useful to be written in a separate, more general rule when the value is 'contain', for instance, while more specific rules change the image source. There may also be some authors who can't remember where to put the slash and background-size value in the shorthand, because it is such a long, complex syntax.
I don't think any of these issues would apply to color(). Font shorthand shows that authors are not adverse to using a slash when it makes sense and is easy to do so.
@fantasai I really like your idea of using e.g. hsl (and presumably hwb, lab, lch, gray, etc.) as just another colorspace keyword in the color() value. It makes me wonder if we really need separate functions for hwb, lab, lch, gray, etc.
In other words, why have lab(50,80,160)
if you already have color(lab 50,80,160)
? It would be one color function to rule them all! That would make the syntax very simple to remember, too, because it would be such a consistent way to write colors (even though it is a few extra characters).
Oops. I meant to say:
Why have lab(50,80,160)
(or lab(50 80 160)
) if you already have color(lab 50 80 160)
?
Ok, we seem to be in full bikeshed mode already, so did we consider
color(hsl 50% 50% 50% a 50%)
?
That seems more clear than a slash or comma that seems to be lost there in the middle of the function (at least that's the impression it gives me when I see it). It would also be a nice notation for other things like
color(rgb $r $g $b h 180deg)
to invert the hue of a color itself defined in rgb for instance.
I'm not too keen on one-letter abbreviations. Would 's' stand for 'saturation' or 'shade'? I find the whole color-mod
section of the spec to be confusingly written, and I don't like the OLAs there either. But I would be good with having something like color(rgb 255 0 0 saturation -50%)
. And if we had that, then I guess color(rgb 255 0 0 alpha 50%)
makes sense. Though it is then a lot longer than rgb(255 0 0 / 50%)
. But, it's pretty darn clear.
I wouldn't mind alpha written out entirely, that gives a lot of clarity, but at the same times I think everyone knows that colors have an addition alpha parameter, and a
could be clear enough.
You're right for saturation/shade/etc though, I didn't think this through but yes full identifiers make a lot of sense there.
Note, though, that alpha is a completely arbitrary designation and thus opaque to newcomers. Pun intended.
@crissov good point.
color(rgb 255 0 0 opacity 50%)
On the other hand, opacity/alpha in color is so common, I'd rather use a slash (or even a space, if I can't have that) than to require authors to type out a spelled out word for that. I can't imagine that much added typing would make it popular.
Maybe we should go ahead and have colons in the functional syntax, after the color-mod name. Something like this:
color( [ <colorspace>? [ <number>+ | <string> ] [ / <alpha> ]? [<color-mod-name>: <color-mod-value>]* ]# )
We don't really put colons inside a CSS value syntax, and I think the leading keyword is sufficiently clear. I agree with Brad that using a slash for alpha makes more sense given how common it is.
Wrt replacing all the color functions with color().... that's a lot of unnecessary typing. :) So long as a color doesn't need fallbacks, using its own function is more ergonomic and should therefore be allowed.
Looks like it was decided in the telcon today to accept fantasai's suggested syntax:
color( [ <colorspace>? [ <number>+ | <string> ] [ / <alpha> ]? ]# , <color>? )
(I'm happy with this; the comma usage is to separate fallbacks, which corresponds to the "separating repetitions" usage that CSS normally uses commas for. I still don't think the slash is necessary, but I'm fine with having it, and doing so means it's clear where the alpha is even if you use a <number>
for alpha, or if we in the future allow the colorspace arguments to be <percentage>
s.)
Yes, that is what was decided today and it enables multiple fallbacks without having to use multiple nested functions. The slash is not necessary for a parser and is very helpful for human readers, especially once we get colorspaces with many parameters (such as multi-ink printers).
So this suggests that the comma-less rgb()
/etc syntax we agreed to add should also use the /
to separate the alpha?
Yes, exactly. See the minutes.
Thanks, I hadn't read them completely thru yet. Editting now.
We didn't actually resolve on the parentheses-less color-mod part, but I didn't hear anything against it when I mentioned it. I hope that can go into the next editors draft too.
Also no clear resolution on if we want e.g. rgba(<r>, <g>, <b>)
and rgb(<r>, <g>, <b>, <a>)
(probably not?), but we do want rgb(<r> <g> <b> / <a>)
.
I don't care about rgba(<r> <g> <b> / <a>)
, if that's included in the resolution or not. I'd prefer to only back-port to the non-a functions, since the /<a>
would be available in rgb().
color()'s grammar is:
The comma between the args and alpha is required, as we don't know how many args they are and both can be numbers. The comma between the fallback and the preceding stuff isn't strictly necessary, but it's pretty natural and matches up with other function's fallback arguments.
But the comma between the colorspace name and the arguments isn't necessary. There's no grammatical ambiguity possible, nor any strong tradition of comma usage in similar situations.
Can we remove it? Then we won't need any commas in the common case, like
color(adobe-rgb 255 0 0)
.