W3C home > Mailing lists > Public > www-style@w3.org > January 2015

Re: [cssom] Serializing non-opaque colors, background-position keywords

From: Simon Pieters <simonp@opera.com>
Date: Thu, 29 Jan 2015 12:43:22 +0100
To: www-style@w3.org, "Boris Zbarsky" <bzbarsky@mit.edu>
Cc: "Tab Atkins Jr." <jackalmage@gmail.com>
Message-ID: <op.xs72uk0lidj3kv@simons-mbp>
On Wed, 28 Jan 2015 18:54:44 +0100, Boris Zbarsky <bzbarsky@mit.edu> wrote:

> On 1/28/15 5:10 AM, Simon Pieters wrote:
>> How should color: rgba(5, 7, 10, 0.9) be serialized? Gecko round-trips
>> alpha as 0.9 but Blink makes it 0.901961. I think Gecko faithfully
>> round-trips two decimals for colors.
> Yes.
> Specifically, Gecko's internal storage for the case above is a 32-bit  
> integer, 8 bits each for RGBA.  Which means the 0.9 gets coverted to an  
> integer in the range [0,255], by multiplying it by 255 and then  
> rounding.  This produces 230 in this case.  I assume Blink does the  
> same, since 230 / 255 == 0.901960784314...


> In any case, when converting the integer back to a float, Gecko does the  
> following (code at  
> <http://hg.mozilla.org/mozilla-central/file/9b6b80222e66/layout/style/nsStyleUtil.cpp#l567>  
> but reproduced below as pseudo-code with more extensive comments):
>    // Produce a float with at most two digits after the decimal point,
>    // modulo representability issues.
>    rounded = round(alpha * 100.0 / 255.0) / 100.0;
>    if (round(rounded * 255) == alpha) {
>      // We have a float which would give us the observed alpha value;
>      // use it.
>      return rounded;
>    }
>    // Produce a float with at most three digits after the decimal
>    // point.  More precision that that is pointless, because there are
>    // only 256 possible values of "alpha" anyway, so the 1000 values we
>    // can produce here cover all of them.
>    return round(alpha * 1000.0 / 255.0) / 1000.0;
> This faithfully round-trips two decimals, preserves about 1/4 of  
> three-decimal values, and rounds off all values with more precision to  
> three decimal places (and in fact only to the subset of  
> three-decimal-place values that are multiples of 1/255).


>> Should we specify Gecko's behavior
>> of rounding to a "nicer" number?
> We feel pretty strongly that this behavior is much better for authors in  
> typical situations.  The spec obviously doesn't require browsers to  
> store alpha as an 8-bit integer, but it could require that if they do so  
> they must use an algorithm like the above when serializing the  
> (already-rounded, just in different units) value.

Yes. I agree it seems better for authors.

>> Similarly for 'opacity' (although that is represented with higher
>> precision I think).
> I'd think opacity is typically represented as an actual float... though  
> of course technically CSS requires representation as an  
> infinite-precision decimal or something.

In Blink opacity:0.4 doesn't round-trip as 0.4 with getComputedStyle:


but it does round-trip for element.style:


The getComputedStyle case gets a double -> float -> double roundtrip. For  
the .style case it doesn't go through float.

Filed https://code.google.com/p/chromium/issues/detail?id=453288

As for Gecko, rune helped me find this:


Output up to 6 decimals, but remove trailing 0s. Handling of scientific  
notation is also interesting. There the conversion from float to double is  
still visible with e.g.  

IE11 has the same behavior as Gecko for the cases I've tried (including  

>> How should background-position: 0% top be serialized? For element.style,
>> Gecko round-trips keywords, Blink converts to percentages.
> Interstingly, the devtools in Blink show "0% top" in this case, so  
> either they're not using the actual parsed CSS data structures or the  
> latter are in fact storing the keyword and just converting to 0% at  
> serialization time...

OK. Devtools might be using getMatchedCSSRules() which maybe more  
faithfully preserves the input.

IE11 roundtrips percentages and keywords for .style but converts to  
percentages for .getComputedStyle.


On Wed, 28 Jan 2015 19:52:56 +0100, Tab Atkins Jr. <jackalmage@gmail.com>  

>> == Non-opaque colors ==
> We store alpha with the same resolution as the other channels, as a  
> single byte.
> We could maybe round to the nearest .01 for serialization (which will
> always round-trip values of that precision), but I doubt we'd want to
> expand our precision, as it currently allows us to store a complete
> color in an int32.
> (Or we could do what Boris suggests, and return two or three digits,  
> depending.)

Two digits can't represent all possible values of a byte. e.g. we need  
0.004 to represent 1. So we should probably do what Gecko does.

Interestingly, IE11 seems to do something different entirely.


Alpha of 0.1234567890123456789 gets serialized as 0.123456.

>> Similarly for 'opacity' (although that is represented with higher  
>> precision
>> I think).
> I would be totally fine with specifying that opacity must be
> serialized with 2 or 3 digits.

OK. Presto serializes at most 2 digits. Are people OK with that? Or is the  
Gecko/IE approach better?

>> == background-position keywords ==
>> How should background-position: 0% top be serialized? For element.style,
>> Gecko round-trips keywords, Blink converts to percentages. For
>> getComputedStyle, both convert to percentages. I think the spec for
>> background-position says keywords compute to percentages.
> I'm fine with either percentages or keywords, as long as we don't have
> to remember which was specified and return it.  In other words, I'm
> okay if "top" always becomes 0%, or 0% always becomes "top" (or
> "left", whatever), but I'm not okay with 0% becoming 0% and "top"
> becoming "top".

OK. Why?

Are Gecko/IE OK with not differentiating keywords and percentages in  

> I lean slightly towards percentages, though, as that means the
> serialization doesn't suddenly change at a few magic values.

Simon Pieters
Opera Software
Received on Thursday, 29 January 2015 11:43:55 UTC

This archive was generated by hypermail 2.4.0 : Friday, 25 March 2022 10:08:50 UTC