typestyle / csx

Utility functions for TypeStyle
https://typestyle.github.io
MIT License
102 stars 14 forks source link

rgba (and any percentage) can return different values on server and in client #33

Closed magnushiie closed 7 years ago

magnushiie commented 7 years ago

Because of different floating point implementations, it can happen that the styles rendered on server are different from the ones rendered in the client (e.g. in universal React app), which causes a warning in React.

I have a style that has a color rgba(255,242,216,0.49), this is rendered in the client as rgba(255,242,216,0.49000000000000005) and on server as rgba(255,242,216,0.49000000000000027).

rgba uses roundFloat but it just discards significant digits but does not discard floating point representation errors, perhaps it should return a string and truncate? https://github.com/typestyle/csx/blob/b29ed7d934db852148faed2e9ff578f7cf3ee21a/src/internal/color.ts#L461-L463

notoriousb1t commented 7 years ago

That sounds reasonable. I think the most succinct way to do that is to do something like...

var alphaText = /^(\-?\d+\.?\d{0,5})/.execute(i.toString())[1]

I will start adding this in an hour or so.

magnushiie commented 7 years ago

How about using Number.toFixed(5)?

notoriousb1t commented 7 years ago

This has been fixed in https://github.com/typestyle/csx/commit/4c69c52dfc51b1a2647bc99bd6a207bd9e72666f in version 8.4.0

I changed the method of doing float rounding and added in code to truncate after 5 decimal places for alpha and percentage values.

Let me know if that works for you :)

notoriousb1t commented 7 years ago

(2).toFixed(5) would output 2.00000. That seems unnecessary.

magnushiie commented 7 years ago

I think just truncation is not enough (at least without adding some small constant), otherwise you can sometimes end up with constants like 1.99999 (floating point representation can end up erring on both sides). toFixed with truncation of trailing zeroes would probably work best.

magnushiie commented 7 years ago

E.g.

(23-7.37).toString()
"15.629999999999999"
(23-7.37).toFixed(5)
"15.63000"
notoriousb1t commented 7 years ago

That case is covered 😄 I changed the methodology of float rounding, and that fixed the floating point issues.

Essentially this is happening

var n = 23 - 7.37
var alpha = Math.round(n * 10000) / 10000  // 15.63
var alphaString = /^(\-?\d+\.?\d{0,5})/.exec(alpha.toString())[1]  // "15.63"

So that should solve the issue without adding extra digits